summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--3rdparty/ymfm/src/ymfm_fm.ipp4
-rw-r--r--3rdparty/ymfm/src/ymfm_opq.cpp18
-rw-r--r--3rdparty/ymfm/src/ymfm_opq.h25
-rw-r--r--3rdparty/ymfm/src/ymfm_opz.cpp189
-rw-r--r--3rdparty/ymfm/src/ymfm_opz.h26
-rw-r--r--scripts/src/sound.lua4
-rw-r--r--scripts/src/tools.lua2
-rw-r--r--src/devices/imagedev/floppy.cpp22
-rw-r--r--src/devices/imagedev/floppy.h10
-rw-r--r--src/devices/machine/z80scc.cpp7
-rw-r--r--src/devices/sound/ymopq.cpp22
-rw-r--r--src/devices/sound/ymopq.h18
-rw-r--r--src/lib/formats/all.h2
-rw-r--r--src/lib/formats/fs_oric_jasmin.cpp20
-rw-r--r--src/lib/formats/fs_oric_jasmin.h5
-rw-r--r--src/lib/formats/fs_prodos.cpp179
-rw-r--r--src/lib/formats/fs_prodos.h35
-rw-r--r--src/lib/formats/fs_unformatted.cpp14
-rw-r--r--src/lib/formats/fs_unformatted.h5
-rw-r--r--src/lib/formats/fsmgr.h15
-rw-r--r--src/mame/drivers/model1.cpp116
-rw-r--r--src/mame/drivers/saitek_leonardo.cpp20
-rw-r--r--src/mame/drivers/saitek_renaissance.cpp20
-rw-r--r--src/mame/drivers/snowbros.cpp53
-rw-r--r--src/mame/drivers/xerox820.cpp70
-rw-r--r--src/mame/drivers/ympsr60.cpp18
-rw-r--r--src/mame/drivers/ymtx81z.cpp9
-rw-r--r--src/mame/includes/snowbros.h1
-rw-r--r--src/mame/includes/xerox820.h7
-rw-r--r--src/mame/mame.lst1
-rw-r--r--src/tools/floptool.cpp953
-rw-r--r--src/tools/image_handler.cpp481
-rw-r--r--src/tools/image_handler.h121
33 files changed, 1388 insertions, 1104 deletions
diff --git a/3rdparty/ymfm/src/ymfm_fm.ipp b/3rdparty/ymfm/src/ymfm_fm.ipp
index 3f85a241283..0c51a1528cf 100644
--- a/3rdparty/ymfm/src/ymfm_fm.ipp
+++ b/3rdparty/ymfm/src/ymfm_fm.ipp
@@ -768,7 +768,7 @@ void fm_operator<RegisterType>::clock_phase(int32_t lfo_raw_pm)
template<class RegisterType>
uint32_t fm_operator<RegisterType>::envelope_attenuation(uint32_t am_offset) const
{
- uint32_t result = m_env_attenuation;
+ uint32_t result = m_env_attenuation >> m_cache.eg_shift;
// invert if necessary due to SSG-EG
if (RegisterType::EG_HAS_SSG && m_ssg_inverted)
@@ -782,7 +782,7 @@ uint32_t fm_operator<RegisterType>::envelope_attenuation(uint32_t am_offset) con
result += m_cache.total_level;
// clamp to max, apply shift, and return
- return std::min<uint32_t>(result, 0x3ff) >> m_cache.eg_shift;
+ return std::min<uint32_t>(result, 0x3ff);
}
diff --git a/3rdparty/ymfm/src/ymfm_opq.cpp b/3rdparty/ymfm/src/ymfm_opq.cpp
index e886722876b..02d8c35a5a8 100644
--- a/3rdparty/ymfm/src/ymfm_opq.cpp
+++ b/3rdparty/ymfm/src/ymfm_opq.cpp
@@ -31,6 +31,8 @@
#include "ymfm_opq.h"
#include "ymfm_fm.ipp"
+#define TEMPORARY_DEBUG_PRINTS (1)
+
//
// OPQ (aka YM3806/YM3533)
//
@@ -126,9 +128,11 @@ bool opq_registers::write(uint16_t index, uint8_t data, uint32_t &channel, uint3
// detune/multiple share a register based on the MSB of what is written
// remap the multiple values to 100-11F
- if ((index & 0xe0) == 0x40 && bitfield(data, 7))
+ if ((index & 0xe0) == 0x40 && bitfield(data, 7) != 0)
index += 0xc0;
+ m_regdata[index] = data;
+
// handle writes to the key on index
if (index == 0x05)
{
@@ -425,16 +429,17 @@ uint8_t ym3806::read_status()
uint8_t ym3806::read(uint32_t offset)
{
uint8_t result = 0xff;
- switch (offset & 1)
+ switch (offset)
{
- case 0: // data port (unused)
- debug::log_unexpected_read_write("Unexpected read from YM3806 offset %d\n", offset & 3);
+ case 0: // status port
+ result = read_status();
break;
- case 1: // status port, YM2203 compatible
- result = read_status();
+ default: // unknown
+ debug::log_unexpected_read_write("Unexpected read from YM3806 offset %02X\n", offset);
break;
}
+if (TEMPORARY_DEBUG_PRINTS && offset != 0) printf("Read %02X = %02X\n", offset, result);
return result;
}
@@ -446,6 +451,7 @@ uint8_t ym3806::read(uint32_t offset)
void ym3806::write(uint32_t offset, uint8_t data)
{
+if (TEMPORARY_DEBUG_PRINTS && (offset != 3 || data != 0x71)) printf("Write %02X = %02X\n", offset, data);
// write the FM register
m_fm.write(offset, data);
}
diff --git a/3rdparty/ymfm/src/ymfm_opq.h b/3rdparty/ymfm/src/ymfm_opq.h
index a61dee5ba54..10b91266e9d 100644
--- a/3rdparty/ymfm/src/ymfm_opq.h
+++ b/3rdparty/ymfm/src/ymfm_opq.h
@@ -176,15 +176,15 @@ public:
// system-wide registers
uint32_t timer_a_value() const { return 0; }
- uint32_t timer_b_value() const { return byte(0x03, 0, 8); }
+ uint32_t timer_b_value() const { return byte(0x03, 2, 6) | 0xc0; } // ???
uint32_t csm() const { return 0; }
- uint32_t reset_timer_b() const { return byte(0x14, 5, 1); }
+ uint32_t reset_timer_b() const { return byte(0x03, 0, 1); } // ???
uint32_t reset_timer_a() const { return 0; }
- uint32_t enable_timer_b() const { return byte(0x14, 3, 1); }
+ uint32_t enable_timer_b() const { return byte(0x03, 0, 1); } // ???
uint32_t enable_timer_a() const { return 0; }
- uint32_t load_timer_b() const { return byte(0x14, 1, 1); }
+ uint32_t load_timer_b() const { return byte(0x03, 0, 1); } // ???
uint32_t load_timer_a() const { return 0; }
- uint32_t lfo_enable() const { return byte(0x04, 4, 1) ^ 1; }
+ uint32_t lfo_enable() const { return byte(0x04, 3, 1) ^ 1; }
uint32_t lfo_rate() const { return byte(0x04, 0, 3); }
// per-channel registers
@@ -198,8 +198,8 @@ public:
uint32_t ch_echo(uint32_t choffs) const { return byte(0x18, 7, 1, choffs); }
uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return byte(0x18, 4, 3, choffs); }
uint32_t ch_lfo_am_sens(uint32_t choffs) const { return byte(0x18, 0, 2, choffs); }
- uint32_t ch_block_freq_24(uint32_t choffs) const { return word(0x20, 0, 6, 0x30, 0, 8, choffs); }
- uint32_t ch_block_freq_13(uint32_t choffs) const { return word(0x28, 0, 6, 0x30, 0, 8, choffs); }
+ uint32_t ch_block_freq_24(uint32_t choffs) const { return word(0x20, 0, 7, 0x30, 0, 8, choffs); }
+ uint32_t ch_block_freq_13(uint32_t choffs) const { return word(0x28, 0, 7, 0x38, 0, 8, choffs); }
// per-operator registers
uint32_t op_detune(uint32_t opoffs) const { return byte(0x40, 0, 6, opoffs); }
@@ -279,6 +279,17 @@ protected:
fm_engine m_fm; // core FM engine
};
+
+// ======================> ym3533
+
+class ym3533 : public ym3806
+{
+public:
+ // constructor
+ ym3533(ymfm_interface &intf) :
+ ym3806(intf) { }
+};
+
}
diff --git a/3rdparty/ymfm/src/ymfm_opz.cpp b/3rdparty/ymfm/src/ymfm_opz.cpp
index ae814e45b13..8ee0cd9ab66 100644
--- a/3rdparty/ymfm/src/ymfm_opz.cpp
+++ b/3rdparty/ymfm/src/ymfm_opz.cpp
@@ -31,6 +31,8 @@
#include "ymfm_opz.h"
#include "ymfm_fm.ipp"
+#define TEMPORARY_DEBUG_PRINTS (0)
+
//
// OPZ (aka YM2414)
//
@@ -102,10 +104,15 @@ opz_registers::opz_registers() :
for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++)
m_waveform[0][index] = abs_sin_attenuation(index) | (bitfield(index, 9) << 15);
+ // we only have the diagrams to judge from, but suspecting waveform 1 (and
+ // derived waveforms) are sin^2, based on OPX description of similar wave-
+ // forms; since our sin table is logarithmic, this ends up just being
+ // 2*existing value
uint16_t zeroval = m_waveform[0][0];
for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++)
- m_waveform[1][index] = (zeroval - m_waveform[0][(index & 0x1ff) ^ 0x100]) | (bitfield(index, 9) << 15);
+ m_waveform[1][index] = std::min<uint16_t>(2 * (m_waveform[0][index] & 0x7fff), zeroval) | (bitfield(index, 9) << 15);
+ // remaining waveforms are just derivations of the 2 main ones
for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++)
{
m_waveform[2][index] = bitfield(index, 9) ? zeroval : m_waveform[0][index];
@@ -209,17 +216,17 @@ bool opz_registers::write(uint16_t index, uint8_t data, uint32_t &channel, uint3
assert(index < REGISTERS);
// special mappings:
- // 0x16 -> 0x148 if bit 7 is set
- // 0x19 -> 0x149 if bit 7 is set
- // 0x38..0x3F -> 0x140..0x147 if bit 7 is set
+ // 0x16 -> 0x188 if bit 7 is set
+ // 0x19 -> 0x189 if bit 7 is set
+ // 0x38..0x3F -> 0x180..0x187 if bit 7 is set
// 0x40..0x5F -> 0x100..0x11F if bit 7 is set
// 0xC0..0xDF -> 0x120..0x13F if bit 5 is set
if (index == 0x17 && bitfield(data, 7) != 0)
- m_regdata[0x148] = data;
+ m_regdata[0x188] = data;
else if (index == 0x19 && bitfield(data, 7) != 0)
- m_regdata[0x149] = data;
+ m_regdata[0x189] = data;
else if ((index & 0xf8) == 0x38 && bitfield(data, 7) != 0)
- m_regdata[0x140 + (index & 7)] = data;
+ m_regdata[0x180 + (index & 7)] = data;
else if ((index & 0xe0) == 0x40 && bitfield(data, 7) != 0)
m_regdata[0x100 + (index & 0x1f)] = data;
else if ((index & 0xe0) == 0xc0 && bitfield(data, 5) != 0)
@@ -227,16 +234,60 @@ bool opz_registers::write(uint16_t index, uint8_t data, uint32_t &channel, uint3
else if (index < 0x100)
m_regdata[index] = data;
+ // preset writes restore some values from a preset memory; not sure
+ // how this really works but the TX81Z will overwrite the sustain level/
+ // release rate register and the envelope shift/reverb rate register to
+ // dampen sound, then write the preset number to register 8 to restore them
+ if (index == 0x08)
+ {
+ int chan = bitfield(data, 0, 3);
+ if (TEMPORARY_DEBUG_PRINTS)
+ printf("Loading preset %d\n", chan);
+ m_regdata[0xe0 + chan + 0] = m_regdata[0x140 + chan + 0];
+ m_regdata[0xe0 + chan + 8] = m_regdata[0x140 + chan + 8];
+ m_regdata[0xe0 + chan + 16] = m_regdata[0x140 + chan + 16];
+ m_regdata[0xe0 + chan + 24] = m_regdata[0x140 + chan + 24];
+ m_regdata[0x120 + chan + 0] = m_regdata[0x160 + chan + 0];
+ m_regdata[0x120 + chan + 8] = m_regdata[0x160 + chan + 8];
+ m_regdata[0x120 + chan + 16] = m_regdata[0x160 + chan + 16];
+ m_regdata[0x120 + chan + 24] = m_regdata[0x160 + chan + 24];
+ }
+
+ // store the presets under some unknown condition; the pattern of writes
+ // when setting a new preset is:
+ //
+ // 08 (0-7), 80-9F, A0-BF, C0-DF, C0-DF (alt), 20-27, 40-5F, 40-5F (alt),
+ // C0-DF (alt -- again?), 38-3F, 1B, 18, E0-FF
+ //
+ // So it writes 0-7 to 08 to either reset all presets or to indicate
+ // that we're going to be loading them. Immediately after all the writes
+ // above, the very next write will be temporary values to blow away the
+ // values loaded into E0-FF, so somehow it also knows that anything after
+ // that point is not part of the preset.
+ //
+ // For now, try using the 40-5F (alt) writes as flags that presets are
+ // being loaded until the E0-FF writes happen.
+ bool is_setting_preset = (bitfield(m_regdata[0x100 + (index & 0x1f)], 7) != 0);
+ if (is_setting_preset)
+ {
+ if ((index & 0xe0) == 0xe0)
+ {
+ m_regdata[0x140 + (index & 0x1f)] = data;
+ m_regdata[0x100 + (index & 0x1f)] &= 0x7f;
+ }
+ else if ((index & 0xe0) == 0xc0 && bitfield(data, 5) != 0)
+ m_regdata[0x160 + (index & 0x1f)] = data;
+ }
+
// handle writes to the key on index
if ((index & 0xf8) == 0x20 && bitfield(index, 0, 3) == bitfield(m_regdata[0x08], 0, 3))
{
channel = bitfield(index, 0, 3);
- opmask = ch_key_on(channel) ? 0xf : 0; //bitfield(data, 3, 4);
+ opmask = ch_key_on(channel) ? 0xf : 0;
// according to the TX81Z manual, the sync option causes the LFOs
- // to reset at each note on; assume that's when operator 4 gets
- // a note on signal
- if (bitfield(opmask, 3) != 0)
+ // to reset at each note on
+ if (opmask != 0)
{
if (lfo_sync())
m_lfo_counter[0] = 0;
@@ -372,10 +423,12 @@ void opz_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata
// detune adjustment
cache.detune = detune_adjustment(op_detune(opoffs), keycode);
- // multiple value, as an x.1 value (0 means 0.5)
- cache.multiple = op_multiple(opoffs) * 2;
+ // multiple value, as an x.4 value (0 means 0.5)
+ // the "fine" control provides the fractional bits
+ cache.multiple = op_multiple(opoffs) << 4;
if (cache.multiple == 0)
- cache.multiple = 1;
+ cache.multiple = 0x08;
+ cache.multiple |= op_fine(opoffs);
// phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on
// block_freq, detune, and multiple, so compute it after we've done those;
@@ -439,6 +492,10 @@ uint32_t opz_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd
substep += 75 * freq;
phase_step = substep >> 12;
m_phase_substep[opoffs] = substep & 0xfff;
+
+ // detune/multiple occupy the same space as fix_range/fix_frequency so
+ // don't apply them in addition
+ return phase_step;
}
else
{
@@ -447,9 +504,6 @@ uint32_t opz_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd
static const int16_t s_detune2_delta[4] = { 0, (600*64+50)/100, (781*64+50)/100, (950*64+50)/100 };
int32_t delta = s_detune2_delta[op_detune2(opoffs)];
- // the fine parameter seems to add 1/16th of an octave per unit
- delta += op_fine(opoffs) * (12*64)/16;
-
// add in the PM deltas
uint32_t pm_sensitivity = ch_lfo_pm_sens(choffs);
if (pm_sensitivity != 0)
@@ -481,13 +535,13 @@ uint32_t opz_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd
// apply delta and convert to a frequency number; this translation is
// the same as OPM so just re-use that helper
phase_step = opm_key_code_to_phase_step(cache.block_freq, delta);
- }
- // apply detune based on the keycode
- phase_step += cache.detune;
+ // apply detune based on the keycode
+ phase_step += cache.detune;
- // apply frequency multiplier (which is cached as an x.1 value)
- return (phase_step * cache.multiple) >> 1;
+ // apply frequency multiplier (which is cached as an x.4 value)
+ return (phase_step * cache.multiple) >> 4;
+ }
}
@@ -650,51 +704,54 @@ void ym2414::write_data(uint8_t data)
{
// write the FM register
m_fm.write(m_address, data);
- switch (m_address & 0xe0)
+ if (TEMPORARY_DEBUG_PRINTS)
{
- case 0x00:
- printf("CTL %02X = %02X\n", m_address, data);
- break;
-
- case 0x20:
- switch (m_address & 0xf8)
- {
- case 0x20: printf("R/FBL/ALG %d = %02X\n", m_address & 7, data); break;
- case 0x28: printf("KC %d = %02X\n", m_address & 7, data); break;
- case 0x30: printf("KF/M %d = %02X\n", m_address & 7, data); break;
- case 0x38: printf("PMS/AMS %d = %02X\n", m_address & 7, data); break;
- }
- break;
-
- case 0x40:
- if (bitfield(data, 7) == 0)
- printf("DT1/MUL %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- else
- printf("OW/FINE %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- break;
-
- case 0x60:
- printf("TL %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- break;
-
- case 0x80:
- printf("KRS/FIX/AR %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- break;
-
- case 0xa0:
- printf("A/D1R %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- break;
-
- case 0xc0:
- if (bitfield(data, 5) == 0)
- printf("DT2/D2R %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- else
- printf("EGS/REV %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- break;
-
- case 0xf0:
- printf("D1L/RR %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
- break;
+ switch (m_address & 0xe0)
+ {
+ case 0x00:
+ printf("CTL %02X = %02X\n", m_address, data);
+ break;
+
+ case 0x20:
+ switch (m_address & 0xf8)
+ {
+ case 0x20: printf("R/FBL/ALG %d = %02X\n", m_address & 7, data); break;
+ case 0x28: printf("KC %d = %02X\n", m_address & 7, data); break;
+ case 0x30: printf("KF/M %d = %02X\n", m_address & 7, data); break;
+ case 0x38: printf("PMS/AMS %d = %02X\n", m_address & 7, data); break;
+ }
+ break;
+
+ case 0x40:
+ if (bitfield(data, 7) == 0)
+ printf("DT1/MUL %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ else
+ printf("OW/FINE %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ break;
+
+ case 0x60:
+ printf("TL %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ break;
+
+ case 0x80:
+ printf("KRS/FIX/AR %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ break;
+
+ case 0xa0:
+ printf("A/D1R %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ break;
+
+ case 0xc0:
+ if (bitfield(data, 5) == 0)
+ printf("DT2/D2R %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ else
+ printf("EGS/REV %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ break;
+
+ case 0xe0:
+ printf("D1L/RR %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data);
+ break;
+ }
}
// special cases
diff --git a/3rdparty/ymfm/src/ymfm_opz.h b/3rdparty/ymfm/src/ymfm_opz.h
index 3a6bd5733cd..c38dd246ab9 100644
--- a/3rdparty/ymfm/src/ymfm_opz.h
+++ b/3rdparty/ymfm/src/ymfm_opz.h
@@ -49,11 +49,7 @@ namespace ymfm
// OPZ register map:
//
// System-wide registers:
-// 08 -x------ Key on/off operator 4
-// --x----- Key on/off operator 3
-// ---x---- Key on/off operator 2
-// ----x--- Key on/off operator 1
-// -----xxx Channel select
+// 08 -----xxx Load preset (not sure how it gets saved)
// 0F x------- Noise enable
// ---xxxxx Noise frequency
// 10 xxxxxxxx Timer A value (upper 8 bits)
@@ -117,10 +113,14 @@ namespace ymfm
// ----xxxx Fine? (0-15)
// 120-13F xx------ Envelope generator shift (0-3)
// -----xxx Reverb rate (0-7)
-// 140-147 -xxx---- LFO #2 PM sensitivity
+// 140-15F xxxx---- Preset sustain level (0-15)
+// ----xxxx Preset release rate (0-15)
+// 160-17F xx------ Envelope generator shift (0-3)
+// -----xxx Reverb rate (0-7)
+// 180-187 -xxx---- LFO #2 PM sensitivity
// ---- xxx LFO #2 AM shift
-// 148 -xxxxxxx LFO #2 PM depth
-// 149 -xxxxxxx LFO PM depth
+// 188 -xxxxxxx LFO #2 PM depth
+// 189 -xxxxxxx LFO PM depth
//
class opz_registers : public fm_registers_base
@@ -135,7 +135,7 @@ public:
static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1;
static constexpr uint32_t OPERATORS = CHANNELS * 4;
static constexpr uint32_t WAVEFORMS = 8;
- static constexpr uint32_t REGISTERS = 0x150;
+ static constexpr uint32_t REGISTERS = 0x190;
static constexpr uint32_t DEFAULT_PRESCALE = 2;
static constexpr uint32_t EG_CLOCK_DIVIDER = 3;
static constexpr uint32_t CSM_TRIGGER_MASK = ALL_CHANNELS;
@@ -205,12 +205,12 @@ public:
uint32_t enable_timer_a() const { return byte(0x14, 2, 1); }
uint32_t load_timer_b() const { return byte(0x14, 1, 1); }
uint32_t load_timer_a() const { return byte(0x14, 0, 1); }
- uint32_t lfo2_pm_depth() const { return byte(0x148, 0, 7); } // fake
+ uint32_t lfo2_pm_depth() const { return byte(0x188, 0, 7); } // fake
uint32_t lfo2_rate() const { return byte(0x16, 0, 8); }
uint32_t lfo2_am_depth() const { return byte(0x17, 0, 7); }
uint32_t lfo_rate() const { return byte(0x18, 0, 8); }
uint32_t lfo_am_depth() const { return byte(0x19, 0, 7); }
- uint32_t lfo_pm_depth() const { return byte(0x149, 0, 7); } // fake
+ uint32_t lfo_pm_depth() const { return byte(0x189, 0, 7); } // fake
uint32_t output_bits() const { return byte(0x1b, 6, 2); }
uint32_t lfo2_sync() const { return byte(0x1b, 5, 1); }
uint32_t lfo_sync() const { return byte(0x1b, 4, 1); }
@@ -230,8 +230,8 @@ public:
uint32_t ch_block_freq(uint32_t choffs) const { return word(0x28, 0, 7, 0x30, 2, 6, choffs); }
uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return byte(0x38, 4, 3, choffs); }
uint32_t ch_lfo_am_sens(uint32_t choffs) const { return byte(0x38, 0, 2, choffs); }
- uint32_t ch_lfo2_pm_sens(uint32_t choffs) const { return byte(0x140, 4, 3, choffs); } // fake
- uint32_t ch_lfo2_am_sens(uint32_t choffs) const { return byte(0x140, 0, 2, choffs); } // fake
+ uint32_t ch_lfo2_pm_sens(uint32_t choffs) const { return byte(0x180, 4, 3, choffs); } // fake
+ uint32_t ch_lfo2_am_sens(uint32_t choffs) const { return byte(0x180, 0, 2, choffs); } // fake
// per-operator registers
uint32_t op_detune(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); }
diff --git a/scripts/src/sound.lua b/scripts/src/sound.lua
index 91c5465f113..6de550d5dde 100644
--- a/scripts/src/sound.lua
+++ b/scripts/src/sound.lua
@@ -1170,8 +1170,8 @@ end
---------------------------------------------------
-- Yamaha FM synthesizers
--@src/devices/sound/ymopm.h,SOUNDS["YM2151"] = true
---@src/devices/sound/ymopm.h,SOUNDS["YM2414"] = true
---@src/devices/sound/ymopm.h,SOUNDS["YM3806"] = true
+--@src/devices/sound/ymopz.h,SOUNDS["YM2414"] = true
+--@src/devices/sound/ymopq.h,SOUNDS["YM3806"] = true
--@src/devices/sound/ymopn.h,SOUNDS["YM2203"] = true
--@src/devices/sound/ymopl.h,SOUNDS["YM2413"] = true
--@src/devices/sound/ymopn.h,SOUNDS["YM2608"] = true
diff --git a/scripts/src/tools.lua b/scripts/src/tools.lua
index b3fb64c30c0..1f1e4215ce8 100644
--- a/scripts/src/tools.lua
+++ b/scripts/src/tools.lua
@@ -609,6 +609,8 @@ includedirs {
}
files {
+ MAME_DIR .. "src/tools/image_handler.cpp",
+ MAME_DIR .. "src/tools/image_handler.h",
MAME_DIR .. "src/tools/floptool.cpp",
}
diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp
index a0b891220ce..c73b7c87cb0 100644
--- a/src/devices/imagedev/floppy.cpp
+++ b/src/devices/imagedev/floppy.cpp
@@ -177,9 +177,9 @@ void format_registration::add(floppy_format_type format)
m_formats.push_back(format);
}
-void format_registration::add(filesystem_manager_type fs)
+void format_registration::add(const filesystem_manager_t &fs)
{
- m_fs.push_back(fs);
+ m_fs.push_back(&fs);
}
void floppy_image_device::default_fm_floppy_formats(format_registration &fr)
@@ -311,12 +311,12 @@ void floppy_image_device::setup_led_cb(led_cb cb)
cur_led_cb = cb;
}
-void floppy_image_device::fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description)
+void floppy_image_device::fs_enum::add(floppy_format_type type, u32 image_size, const char *name, const char *description)
{
- if(manager->can_format())
- m_fid->m_create_fs.emplace_back(fs_info(manager, type, image_size, name, description));
- if(manager->can_read())
- m_fid->m_io_fs.emplace_back(fs_info(manager, type, image_size, name, description));
+ if(m_manager->can_format())
+ m_fid->m_create_fs.emplace_back(fs_info(m_manager, type, image_size, name, description));
+ if(m_manager->can_read())
+ m_fid->m_io_fs.emplace_back(fs_info(m_manager, type, image_size, name, description));
}
void floppy_image_device::fs_enum::add_raw(const char *name, u32 key, const char *description)
@@ -347,11 +347,11 @@ void floppy_image_device::register_formats()
}
fs_enum fse(this);
- for(filesystem_manager_type fmt : fr.m_fs)
+ for(const filesystem_manager_t *fmt : fr.m_fs)
{
- auto ff = fmt();
- ff->enumerate_f(fse, form_factor, variants);
- m_fs_managers.push_back(std::unique_ptr<filesystem_manager_t>(ff));
+ fse.m_manager = fmt;
+ fmt->enumerate_f(fse, form_factor, variants);
+ m_fs_managers.push_back(fmt);
}
}
diff --git a/src/devices/imagedev/floppy.h b/src/devices/imagedev/floppy.h
index c9fdc220ad3..ea3eea381cc 100644
--- a/src/devices/imagedev/floppy.h
+++ b/src/devices/imagedev/floppy.h
@@ -27,14 +27,14 @@ public:
format_registration();
void add(floppy_format_type format);
- void add(filesystem_manager_type fs);
+ void add(const filesystem_manager_t &fs);
void add_fm_containers();
void add_mfm_containers();
void add_pc_formats();
std::vector<floppy_format_type> m_formats;
- std::vector<filesystem_manager_type> m_fs;
+ std::vector<const filesystem_manager_t *> m_fs;
};
class floppy_image_device : public device_t,
@@ -157,9 +157,11 @@ public:
protected:
struct fs_enum : public filesystem_manager_t::floppy_enumerator {
floppy_image_device *m_fid;
+ const filesystem_manager_t *m_manager;
+
fs_enum(floppy_image_device *fid) : filesystem_manager_t::floppy_enumerator(), m_fid(fid) {};
- virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) override;
+ virtual void add(floppy_format_type type, u32 image_size, const char *name, const char *description) override;
virtual void add_raw(const char *name, u32 key, const char *description) override;
};
@@ -188,7 +190,7 @@ protected:
char extension_list[256];
floppy_image_format_t *fif_list;
std::vector<fs_info> m_create_fs, m_io_fs;
- std::vector<std::unique_ptr<filesystem_manager_t>> m_fs_managers;
+ std::vector<const filesystem_manager_t *> m_fs_managers;
emu_timer *index_timer;
/* Physical characteristics, filled by setup_characteristics */
diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp
index 4978ff66d32..1a1dc0a3eda 100644
--- a/src/devices/machine/z80scc.cpp
+++ b/src/devices/machine/z80scc.cpp
@@ -1243,6 +1243,9 @@ void z80scc_channel::tra_callback()
LOGTX("%s: transmit data bit %d m_wr5:%02x\n", FUNCNAME, db, m_wr5);
// transmit data
out_txd_cb(db);
+
+ if (m_wr14 & WR14_LOCAL_LOOPBACK)
+ write_rx(db);
}
else
{
@@ -2298,6 +2301,10 @@ void z80scc_channel::do_sccreg_wr14(uint8_t data)
m_brg_counter = 0;
#endif
}
+
+ if (!(m_wr14 & WR14_LOCAL_LOOPBACK) && (data & WR14_LOCAL_LOOPBACK))
+ receive_register_reset();
+
// TODO: Add info on the other bits of this register
m_wr14 = data;
update_serial();
diff --git a/src/devices/sound/ymopq.cpp b/src/devices/sound/ymopq.cpp
index a65c33424df..3286dd7cf3b 100644
--- a/src/devices/sound/ymopq.cpp
+++ b/src/devices/sound/ymopq.cpp
@@ -5,13 +5,12 @@
#include "ymopq.h"
-DEFINE_DEVICE_TYPE(YM3806, ym3806_device, "ym3806", "YM3806 OPN")
-
-
//*********************************************************
// YM3806 DEVICE
//*********************************************************
+DEFINE_DEVICE_TYPE(YM3806, ym3806_device, "ym3806", "YM3806 OPQ")
+
//-------------------------------------------------
// ym3806_device - constructor
//-------------------------------------------------
@@ -20,3 +19,20 @@ ym3806_device::ym3806_device(const machine_config &mconfig, const char *tag, dev
ymfm_device_base<ymfm::ym3806>(mconfig, tag, owner, clock, YM3806)
{
}
+
+
+
+//*********************************************************
+// YM3533 DEVICE
+//*********************************************************
+
+DEFINE_DEVICE_TYPE(YM3533, ym3533_device, "ym3533", "YM3533 OPQ")
+
+//-------------------------------------------------
+// ym3533_device - constructor
+//-------------------------------------------------
+
+ym3533_device::ym3533_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ ymfm_device_base<ymfm::ym3533>(mconfig, tag, owner, clock, YM3533)
+{
+}
diff --git a/src/devices/sound/ymopq.h b/src/devices/sound/ymopq.h
index 41dac44e413..39a76e7307d 100644
--- a/src/devices/sound/ymopq.h
+++ b/src/devices/sound/ymopq.h
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
-#ifndef MAME_SOUND_YM3806_H
-#define MAME_SOUND_YM3806_H
+#ifndef MAME_SOUND_YMOPQ_H
+#define MAME_SOUND_YMOPQ_H
#pragma once
@@ -21,4 +21,16 @@ public:
ym3806_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
-#endif // MAME_SOUND_YM3806_H
+
+// ======================> ym3533_device
+
+DECLARE_DEVICE_TYPE(YM3533, ym3533_device);
+
+class ym3533_device : public ymfm_device_base<ymfm::ym3533>
+{
+public:
+ // constructor
+ ym3533_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+#endif // MAME_SOUND_YMOPQ_H
diff --git a/src/lib/formats/all.h b/src/lib/formats/all.h
index 63de5560949..1284bf9f509 100644
--- a/src/lib/formats/all.h
+++ b/src/lib/formats/all.h
@@ -18,7 +18,7 @@ struct mame_formats_enumerator {
virtual void category(const char *name) = 0;
virtual void add(const cassette_image::Format *const *formats) = 0;
virtual void add(floppy_format_type format) = 0;
- virtual void add(filesystem_manager_type fs) = 0;
+ virtual void add(const filesystem_manager_t &fs) = 0;
};
void mame_formats_full_list(mame_formats_enumerator &en);
diff --git a/src/lib/formats/fs_oric_jasmin.cpp b/src/lib/formats/fs_oric_jasmin.cpp
index 0b6740c49c3..dadf76026a7 100644
--- a/src/lib/formats/fs_oric_jasmin.cpp
+++ b/src/lib/formats/fs_oric_jasmin.cpp
@@ -7,6 +7,8 @@
#include "fs_oric_jasmin.h"
#include "oric_dsk.h"
+const fs_oric_jasmin FS_ORIC_JASMIN;
+
// Floppy only, format is 41 tracks, 1/2 heads, 17 sectors.
// Filesystem has no subdirectories.
//
@@ -39,12 +41,22 @@
// offset 04-05: length of the file in bytes on the first sector, ffff otherwise
// offset 06+ : reference to data sectors, (ff, ff) when done
+const char *fs_oric_jasmin::name() const
+{
+ return "oric_jasmin";
+}
+
+const char *fs_oric_jasmin::description() const
+{
+ return "Oric Jasmin";
+}
+
void fs_oric_jasmin::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
if(has(form_factor, variants, floppy_image::FF_3, floppy_image::DSDD))
- fe.add(this, FLOPPY_ORIC_JASMIN_FORMAT, 356864, "oric_jasmin_ds", "Oric Jasmin dual-sided");
+ fe.add(FLOPPY_ORIC_JASMIN_FORMAT, 356864, "oric_jasmin_ds", "Oric Jasmin dual-sided");
if(has(form_factor, variants, floppy_image::FF_3, floppy_image::SSDD))
- fe.add(this, FLOPPY_ORIC_JASMIN_FORMAT, 178432, "oric_jasmin_ss", "Oric Jasmin single-sided");
+ fe.add(FLOPPY_ORIC_JASMIN_FORMAT, 178432, "oric_jasmin_ss", "Oric Jasmin single-sided");
}
std::unique_ptr<filesystem_t> fs_oric_jasmin::mount(fsblk_t &blockdev) const
@@ -609,7 +621,3 @@ u32 fs_oric_jasmin::impl::free_block_count()
}
return nf;
}
-
-
-
-const filesystem_manager_type FS_ORIC_JASMIN = &filesystem_manager_creator<fs_oric_jasmin>;;
diff --git a/src/lib/formats/fs_oric_jasmin.h b/src/lib/formats/fs_oric_jasmin.h
index 304fbf1eb05..2ffe27fb7cf 100644
--- a/src/lib/formats/fs_oric_jasmin.h
+++ b/src/lib/formats/fs_oric_jasmin.h
@@ -102,6 +102,9 @@ public:
fs_oric_jasmin() : filesystem_manager_t() {}
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
@@ -116,6 +119,6 @@ public:
static bool validate_filename(std::string name);
};
-extern const filesystem_manager_type FS_ORIC_JASMIN;
+extern const fs_oric_jasmin FS_ORIC_JASMIN;
#endif
diff --git a/src/lib/formats/fs_prodos.cpp b/src/lib/formats/fs_prodos.cpp
index a79c02fb800..a5a6b11eea3 100644
--- a/src/lib/formats/fs_prodos.cpp
+++ b/src/lib/formats/fs_prodos.cpp
@@ -7,6 +7,19 @@
#include "fs_prodos.h"
#include "ap_dsk35.h"
+
+const fs_prodos FS_PRODOS;
+
+const char *fs_prodos::name() const
+{
+ return "prodos";
+}
+
+const char *fs_prodos::description() const
+{
+ return "Apple ProDOS";
+}
+
const u8 fs_prodos::impl::boot[512] = {
0x01, 0x38, 0xb0, 0x03, 0x4c, 0x1c, 0x09, 0x78, 0x86, 0x43, 0xc9, 0x03, 0x08, 0x8a, 0x29, 0x70,
0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, 0x49, 0xa0, 0xff, 0x84, 0x48, 0x28, 0xc8, 0xb1, 0x48,
@@ -45,9 +58,9 @@ const u8 fs_prodos::impl::boot[512] = {
void fs_prodos::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
if(has(form_factor, variants, floppy_image::FF_35, floppy_image::DSDD))
- fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 819200, "prodos_800k", "Apple ProDOS 800K");
+ fe.add(FLOPPY_APPLE_GCR_FORMAT, 819200, "prodos_800k", "Apple ProDOS 800K");
if(has(form_factor, variants, floppy_image::FF_35, floppy_image::SSDD))
- fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 409600, "prodos_400k", "Apple ProDOS 400K");
+ fe.add(FLOPPY_APPLE_GCR_FORMAT, 409600, "prodos_400k", "Apple ProDOS 400K");
}
std::unique_ptr<filesystem_t> fs_prodos::mount(fsblk_t &blockdev) const
@@ -222,7 +235,7 @@ fs_meta_data fs_prodos::impl::metadata()
filesystem_t::dir_t fs_prodos::impl::root()
{
if(!m_root)
- m_root = new dir(*this, 2);
+ m_root = new root_dir(*this, 2);
return m_root.strong();
}
@@ -232,29 +245,18 @@ void fs_prodos::impl::drop_root_ref()
}
-void fs_prodos::impl::dir::drop_weak_references()
+void fs_prodos::impl::root_dir::drop_weak_references()
{
if(m_base_block == 2)
m_fs.drop_root_ref();
}
-fs_meta_data fs_prodos::impl::dir::metadata()
+fs_meta_data fs_prodos::impl::root_dir::metadata()
{
- fs_meta_data res;
- if(m_base_block == 2)
- return res;
-
- auto bdir = m_fs.m_blockdev.get(m_base_block);
- int len = bdir.r8(0x04) & 0xf;
- res.set(fs_meta_name::name, bdir.rstr(0x05, len));
- res.set(fs_meta_name::os_version, bdir.r8(0x20));
- res.set(fs_meta_name::os_minimum_version, bdir.r8(0x21));
- res.set(fs_meta_name::creation_date, prodos_to_dt(bdir.r32l(0x1c)));
- res.set(fs_meta_name::modification_date, prodos_to_dt(bdir.r32l(0x16)));
- return res;
+ return fs_meta_data();
}
-std::vector<fs_dir_entry> fs_prodos::impl::dir::contents()
+std::vector<fs_dir_entry> fs_prodos::impl::root_dir::contents()
{
std::vector<fs_dir_entry> res;
@@ -282,7 +284,8 @@ std::vector<fs_dir_entry> fs_prodos::impl::dir::contents()
return res;
}
-std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::dir::get_entry_ro(uint64_t key)
+
+std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::root_dir::get_entry_ro(uint64_t key)
{
std::pair<fsblk_t::block_t, const u8 *> res;
res.first = m_fs.m_blockdev.get(m_base_block);
@@ -300,7 +303,7 @@ std::pair<fsblk_t::block_t, const u8 *> fs_prodos::impl::dir::get_entry_ro(uint6
return res;
}
-std::pair<fsblk_t::block_t, u8 *> fs_prodos::impl::dir::get_entry(uint64_t key)
+std::pair<fsblk_t::block_t, u8 *> fs_prodos::impl::root_dir::get_entry(uint64_t key)
{
std::pair<fsblk_t::block_t, u8 *> res;
res.first = m_fs.m_blockdev.get(m_base_block);
@@ -318,7 +321,7 @@ std::pair<fsblk_t::block_t, u8 *> fs_prodos::impl::dir::get_entry(uint64_t key)
return res;
}
-filesystem_t::file_t fs_prodos::impl::dir::file_get(uint64_t key)
+filesystem_t::file_t fs_prodos::impl::root_dir::file_get(uint64_t key)
{
auto [blk, entry] = get_entry_ro(key);
if(!blk)
@@ -326,10 +329,10 @@ filesystem_t::file_t fs_prodos::impl::dir::file_get(uint64_t key)
u8 type = entry[0] >> 4;
if(type == 0 || type == 4 || type > 5)
fatalerror("Unhandled file type %x\n", type);
- return new file(m_fs, entry, key);
+ return new file(m_fs, entry, key, this);
}
-filesystem_t::dir_t fs_prodos::impl::dir::dir_get(uint64_t key)
+filesystem_t::dir_t fs_prodos::impl::root_dir::dir_get(uint64_t key)
{
auto [blk, entry] = get_entry_ro(key);
if(!blk)
@@ -338,13 +341,21 @@ filesystem_t::dir_t fs_prodos::impl::dir::dir_get(uint64_t key)
if(type != 0xd)
fatalerror("Unhandled directory type %x\n", type);
- return new dir(m_fs, r16l(entry+0x11), key);
+ return new dir(m_fs, entry, r16l(entry+0x11), key, this);
}
-fs_prodos::impl::file::file(impl &fs, const u8 *entry, u16 key) : m_fs(fs), m_key(key)
+fs_prodos::impl::dir::dir(impl &fs, const u8 *entry, u16 base_block, u16 key, root_dir *parent_dir) : root_dir(fs, base_block), m_parent_dir(parent_dir), m_key(key)
+{
+ memcpy(m_entry, entry, 39);
+ (void)m_key;
+ (void)m_parent_dir;
+}
+
+fs_prodos::impl::file::file(impl &fs, const u8 *entry, u16 key, root_dir *parent_dir) : m_fs(fs), m_parent_dir(parent_dir), m_key(key)
{
memcpy(m_entry, entry, 39);
(void)m_key;
+ (void)m_parent_dir;
}
void fs_prodos::impl::file::drop_weak_references()
@@ -372,32 +383,51 @@ fs_meta_data fs_prodos::impl::file::metadata()
return res;
}
-std::vector<uint16_t> fs_prodos::impl::file::get_file_blocks(uint8_t type, u16 block, u32 length)
+fs_meta_data fs_prodos::impl::dir::metadata()
{
- u32 nb = (length+1)/512;
- std::vector<uint16_t> res;
+ fs_meta_data res;
+ u8 type = r8(m_entry);
+ std::string name = rstr(m_entry+1, type & 0xf);
+ res.set(fs_meta_name::name, name);
+
+ return res;
+}
+
+std::vector<u8> fs_prodos::impl::file::any_read_all(uint8_t type, u16 block, u32 length)
+{
+ std::vector<u8> data((length + 511) & ~511);
+ u32 nb = data.size()/512;
+ if(!nb)
+ return data;
+
+ u8 *dst = data.data();
+ u8 *end = dst + data.size();
switch(type) {
case 1:
- if(nb)
- res.push_back(block);
+ memcpy(dst, m_fs.m_blockdev.get(block).rodata(), 512);
+ dst += 512;
break;
case 2: {
auto iblk = m_fs.m_blockdev.get(block);
- if(nb > 255)
- nb = 255;
- for(u32 i=0; i != nb; i++)
- res.push_back(iblk.r8(i) | (iblk.r8(i | 0x100) << 8));
+ for(u32 i=0; i != 256 && dst != end; i++) {
+ u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
+ memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
+ dst += 512;
+ }
break;
}
case 3: {
auto mblk = m_fs.m_blockdev.get(block);
- for(u32 j=0; j < nb; j += 256) {
+ for(u32 j=0; dst != end; j += 256) {
u32 idx = j/256;
auto iblk = m_fs.m_blockdev.get(mblk.r8(idx) | (mblk.r8(idx | 0x100) << 8));
- for(u32 i=0; i != 256 && res.size() != nb; i++)
- res.push_back(iblk.r8(i) | (iblk.r8(i | 0x100) << 8));
+ for(u32 i=0; i != 256 && dst != end; i++) {
+ u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
+ memcpy(dst, m_fs.m_blockdev.get(blk).rodata(), 512);
+ dst += 512;
+ }
}
break;
}
@@ -405,86 +435,33 @@ std::vector<uint16_t> fs_prodos::impl::file::get_file_blocks(uint8_t type, u16 b
default:
fatalerror("fs_prodos::impl::file::get_file_blocks: unknown file type %d\n", type);
}
- return res;
+
+ data.resize(length);
+ return data;
}
-std::pair<std::vector<uint16_t>, u32> fs_prodos::impl::file::data_blocks()
+std::vector<u8> fs_prodos::impl::file::read_all()
{
- std::vector<uint16_t> blocks;
-
u8 type = r8(m_entry) >> 4;
- u32 length = 0;
- if(type >= 1 && type <= 3) {
- length = r24l(m_entry + 0x15);
- blocks = get_file_blocks(type, r16l(m_entry+0x11), length);
+ if(type >= 1 && type <= 3)
+ return any_read_all(type, r16l(m_entry+0x11), r24l(m_entry + 0x15));
- } else if(type == 5) {
+ else if(type == 5) {
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
- length = kblk.r24l(0x005);
- blocks = get_file_blocks(kblk.r8(0x000), kblk.r16l(0x001), length);
+ return any_read_all(kblk.r8(0x000), kblk.r16l(0x001), kblk.r24l(0x005));
} else
- fatalerror("fs_prodos::impl::file::data_blocks: Unhandled file type %d\n", type);
-
- return std::make_pair(blocks, length);
+ fatalerror("fs_prodos::impl::file::read_all: Unhandled file type %d\n", type);
}
-std::pair<std::vector<uint16_t>, u32> fs_prodos::impl::file::rsrc_blocks()
+std::vector<u8> fs_prodos::impl::file::rsrc_read_all()
{
- std::vector<uint16_t> blocks;
-
u8 type = r8(m_entry) >> 4;
- u32 length = 0;
if(type == 5) {
auto kblk = m_fs.m_blockdev.get(r16l(m_entry+0x11));
- length = kblk.r24l(0x105);
- blocks = get_file_blocks(kblk.r8(0x100), kblk.r16l(0x101), length);
+ return any_read_all(kblk.r8(0x100), kblk.r16l(0x101), kblk.r24l(0x105));
} else
fatalerror("fs_prodos::impl::file::rsrc_blocks: Unhandled file type %d\n", type);
-
- return std::make_pair(blocks, length);
}
-
-std::vector<u8> fs_prodos::impl::file::read_all()
-{
- auto [blocks, length] = data_blocks();
-
- std::vector<u8> data(length);
- u32 pos = 0;
- for(u16 block : blocks) {
- u32 npos = pos + 512;
- if(npos > length)
- npos = length;
- if(npos > pos) {
- auto dblk = m_fs.m_blockdev.get(block);
- memcpy(data.data() + pos, dblk.rodata(), npos - pos);
- } else
- break;
- pos = npos;
- }
- return data;
-}
-
-std::vector<u8> fs_prodos::impl::file::rsrc_read_all()
-{
- auto [blocks, length] = rsrc_blocks();
-
- std::vector<u8> data(length);
- u32 pos = 0;
- for(u16 block : blocks) {
- u32 npos = pos + 512;
- if(npos > length)
- npos = length;
- if(npos > pos) {
- auto dblk = m_fs.m_blockdev.get(block);
- memcpy(data.data() + pos, dblk.rodata(), npos - pos);
- } else
- break;
- pos = npos;
- }
- return data;
-}
-
-const filesystem_manager_type FS_PRODOS = &filesystem_manager_creator<fs_prodos>;;
diff --git a/src/lib/formats/fs_prodos.h b/src/lib/formats/fs_prodos.h
index 626dcbea821..1f5d2405b98 100644
--- a/src/lib/formats/fs_prodos.h
+++ b/src/lib/formats/fs_prodos.h
@@ -14,10 +14,10 @@ class fs_prodos : public filesystem_manager_t {
public:
class impl : public filesystem_t {
public:
- class dir : public idir_t {
+ class root_dir : public idir_t {
public:
- dir(impl &fs, u16 base_block, u16 key = 0) : m_fs(fs), m_base_block(base_block), m_key(key) { (void)m_key; }
- virtual ~dir() = default;
+ root_dir(impl &fs, u16 base_block) : m_fs(fs), m_base_block(base_block) { }
+ virtual ~root_dir() = default;
virtual void drop_weak_references() override;
@@ -26,18 +26,30 @@ public:
virtual file_t file_get(uint64_t key) override;
virtual dir_t dir_get(uint64_t key) override;
- private:
+ protected:
impl &m_fs;
u16 m_base_block;
- u16 m_key;
std::pair<fsblk_t::block_t, const u8 *> get_entry_ro(uint64_t key);
std::pair<fsblk_t::block_t, u8 *> get_entry(uint64_t key);
};
+ class dir : public root_dir {
+ public:
+ dir(impl &fs, const u8 *entry, u16 base_block, u16 key, root_dir *parent_dir);
+ virtual ~dir() = default;
+
+ virtual fs_meta_data metadata() override;
+
+ protected:
+ root_dir *m_parent_dir;
+ u16 m_key;
+ u8 m_entry[39];
+ };
+
class file : public ifile_t {
public:
- file(impl &fs, const u8 *entry, u16 key);
+ file(impl &fs, const u8 *entry, u16 key, root_dir *parent_dir);
virtual ~file() = default;
virtual void drop_weak_references() override;
@@ -48,12 +60,11 @@ public:
private:
impl &m_fs;
+ root_dir *m_parent_dir;
u16 m_key;
u8 m_entry[39];
- std::vector<uint16_t> get_file_blocks(uint8_t type, u16 block, u32 length);
- std::pair<std::vector<uint16_t>, uint32_t> data_blocks();
- std::pair<std::vector<uint16_t>, uint32_t> rsrc_blocks();
+ std::vector<u8> any_read_all(uint8_t type, u16 block, u32 length);
};
impl(fsblk_t &blockdev);
@@ -67,6 +78,7 @@ public:
void drop_root_ref();
static util::arbitrary_datetime prodos_to_dt(u32 date);
+ std::vector<fs_dir_entry> contents(u16 block);
private:
static const u8 boot[512];
@@ -76,6 +88,9 @@ public:
fs_prodos() : filesystem_manager_t() {}
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override;
@@ -90,6 +105,6 @@ public:
virtual std::vector<fs_meta_description> directory_meta_description() const override;
};
-extern const filesystem_manager_type FS_PRODOS;
+extern const fs_prodos FS_PRODOS;
#endif
diff --git a/src/lib/formats/fs_unformatted.cpp b/src/lib/formats/fs_unformatted.cpp
index 2dc927b70fd..81df9ecae69 100644
--- a/src/lib/formats/fs_unformatted.cpp
+++ b/src/lib/formats/fs_unformatted.cpp
@@ -6,6 +6,18 @@
#include "emu.h"
#include "fs_unformatted.h"
+const fs_unformatted FS_UNFORMATTED;
+
+const char *fs_unformatted::name() const
+{
+ return "unformatted";
+}
+
+const char *fs_unformatted::description() const
+{
+ return "Unformatted floppy image";
+}
+
void fs_unformatted::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
bool all = form_factor == floppy_image::FF_UNKNOWN;
@@ -120,5 +132,3 @@ bool fs_unformatted::has_rsrc() const
{
return false;
}
-
-const filesystem_manager_type FS_UNFORMATTED = &filesystem_manager_creator<fs_unformatted>;
diff --git a/src/lib/formats/fs_unformatted.h b/src/lib/formats/fs_unformatted.h
index fe5ac68973d..d3c741013a5 100644
--- a/src/lib/formats/fs_unformatted.h
+++ b/src/lib/formats/fs_unformatted.h
@@ -38,6 +38,9 @@ public:
fs_unformatted() : filesystem_manager_t() {}
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+
static void format(u32 key, floppy_image *image);
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
@@ -49,6 +52,6 @@ public:
virtual bool has_rsrc() const override;
};
-extern const filesystem_manager_type FS_UNFORMATTED;
+extern const fs_unformatted FS_UNFORMATTED;
#endif
diff --git a/src/lib/formats/fsmgr.h b/src/lib/formats/fsmgr.h
index 4546e83d89b..8ae9ddeb452 100644
--- a/src/lib/formats/fsmgr.h
+++ b/src/lib/formats/fsmgr.h
@@ -391,7 +391,7 @@ public:
struct floppy_enumerator {
virtual ~floppy_enumerator() = default;
- virtual void add(const filesystem_manager_t *manager, floppy_format_type type, uint32_t image_size, const char *name, const char *description) = 0;
+ virtual void add(floppy_format_type type, uint32_t image_size, const char *name, const char *description) = 0;
virtual void add_raw(const char *name, uint32_t key, const char *description) = 0;
};
@@ -410,6 +410,9 @@ public:
virtual ~filesystem_manager_t() = default;
+ virtual const char *name() const = 0;
+ virtual const char *description() const = 0;
+
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const;
virtual void enumerate_h(hd_enumerator &he) const;
virtual void enumerate_c(cdrom_enumerator &ce) const;
@@ -436,14 +439,4 @@ protected:
static bool has_variant(const std::vector<uint32_t> &variants, uint32_t variant);
};
-
-typedef filesystem_manager_t *(*filesystem_manager_type)();
-
-// this template function creates a stub which constructs a filesystem manager
-template<class _FormatClass>
-filesystem_manager_t *filesystem_manager_creator()
-{
- return new _FormatClass();
-}
-
#endif
diff --git a/src/mame/drivers/model1.cpp b/src/mame/drivers/model1.cpp
index 442dcc18484..cb233c62586 100644
--- a/src/mame/drivers/model1.cpp
+++ b/src/mame/drivers/model1.cpp
@@ -1198,17 +1198,17 @@ ROM_START( vf )
ROM_LOAD( "epr-16080.4", 0xfc0000, 0x20000, CRC(3662e1a5) SHA1(6bfceb1a7c1c7912679c907f2b7516ae9c7dda67) )
ROM_LOAD( "epr-16081.5", 0xfe0000, 0x20000, CRC(6dec06ce) SHA1(7891544456bccd2fc647bccd058945ad50466636) )
- ROM_LOAD16_BYTE( "mpr-16084.6", 0x1000000, 0x80000, CRC(483f453b) SHA1(41a5527be73f5dd1c87b2a8113235bdd247ec049) )
- ROM_LOAD16_BYTE( "mpr-16085.7", 0x1000001, 0x80000, CRC(5fa01277) SHA1(dfa7ddff0a7daf29071431f26b93dd8e8e5793b6) )
- ROM_LOAD16_BYTE( "mpr-16086.8", 0x1100000, 0x80000, CRC(deac47a1) SHA1(3a8016124e4dc579d4aae745d4af1905ad0e4fbd) )
- ROM_LOAD16_BYTE( "mpr-16087.9", 0x1100001, 0x80000, CRC(7a64daac) SHA1(da6a9cad4b0cb2af4299e664c0889f3fbdc25530) )
+ ROM_LOAD16_BYTE( "mpr-16084.6", 0x1000000, 0x80000, CRC(483f453b) SHA1(41a5527be73f5dd1c87b2a8113235bdd247ec049) )
+ ROM_LOAD16_BYTE( "mpr-16085.7", 0x1000001, 0x80000, CRC(5fa01277) SHA1(dfa7ddff0a7daf29071431f26b93dd8e8e5793b6) )
+ ROM_LOAD16_BYTE( "mpr-16086.8", 0x1100000, 0x80000, CRC(deac47a1) SHA1(3a8016124e4dc579d4aae745d4af1905ad0e4fbd) )
+ ROM_LOAD16_BYTE( "mpr-16087.9", 0x1100001, 0x80000, CRC(7a64daac) SHA1(da6a9cad4b0cb2af4299e664c0889f3fbdc25530) )
ROM_LOAD16_BYTE( "mpr-16088.10", 0x1200000, 0x80000, CRC(fcda2d1e) SHA1(0f7d0f604d429a1da0d1c3f31694520bada49680) )
ROM_LOAD16_BYTE( "mpr-16089.11", 0x1200001, 0x80000, CRC(39befbe0) SHA1(362c493092cd0536fadee7326ecc7f973e23fb58) )
ROM_LOAD16_BYTE( "mpr-16090.12", 0x1300000, 0x80000, CRC(90c76831) SHA1(5a3c25f2a131cfbb2ad067bef1ab7b1c95645d41) )
ROM_LOAD16_BYTE( "mpr-16091.13", 0x1300001, 0x80000, CRC(53115448) SHA1(af798d5b1fcb720d7288a5ac48839d9ace16a2f2) )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5724.bin", 0, 0x2000, CRC(4b4f330e) SHA1(8809d93d47593f808faca55161999677ac7a3eb0) BAD_DUMP )
+ ROM_LOAD( "315-5724.bin", 0, 0x2000, CRC(4b4f330e) SHA1(8809d93d47593f808faca55161999677ac7a3eb0) BAD_DUMP )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
ROM_LOAD16_WORD_SWAP( "epr-16120.7", 0x00000, 0x20000, CRC(2bff8378) SHA1(854b08ab983e4e98cb666f2f44de9a6829b1eb52) )
@@ -1260,7 +1260,7 @@ ROM_START( vr )
ROM_LOAD16_BYTE( "mpr-14889.13", 0x1300001, 0x80000, CRC(c49f0486) SHA1(cc2bb9059c016ba2c4f6e7508bd1687df07b8b48) )
ROM_REGION( 0x2000, "tgp_copro", 0 ) /* TGP program rom */
- ROM_LOAD("315-5573.bin", 0, 0x2000, CRC(3335a19b) SHA1(72eedfcc799ec4c7534fd7415de6631087ff6731) )
+ ROM_LOAD( "315-5573.bin", 0, 0x2000, CRC(3335a19b) SHA1(72eedfcc799ec4c7534fd7415de6631087ff6731) )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
ROM_LOAD16_WORD_SWAP( "epr-14870a.7", 0x00000, 0x20000, CRC(919d9b75) SHA1(27be79881cc9a2b5cf37e18f1e2d87251426b428) )
@@ -1288,7 +1288,7 @@ ROM_START( vr )
ROM_LOAD32_BYTE( "mpr-14901.42", 0x000003, 0x80000, CRC(175b7a9a) SHA1(c86602e771cd49bab425b4ba7926d2f44858bd39) )
ROM_REGION16_LE(0x80, "ioboard:eeprom", 0)
- ROM_LOAD("93c45.bin", 0x00, 0x80, CRC(65aac303) SHA1(17687fedf1578e977cae4e7c3f5c00cad4aa490d) )
+ ROM_LOAD( "93c45.bin", 0x00, 0x80, CRC(65aac303) SHA1(17687fedf1578e977cae4e7c3f5c00cad4aa490d) )
ROM_END
ROM_START( vformula )
@@ -1311,7 +1311,7 @@ ROM_START( vformula )
ROM_LOAD16_BYTE( "mpr-14889.13", 0x1300001, 0x80000, CRC(c49f0486) SHA1(cc2bb9059c016ba2c4f6e7508bd1687df07b8b48) )
ROM_REGION( 0x2000, "tgp_copro", 0 ) /* TGP program rom */
- ROM_LOAD("315-5573.bin", 0, 0x2000, CRC(3335a19b) SHA1(72eedfcc799ec4c7534fd7415de6631087ff6731) )
+ ROM_LOAD( "315-5573.bin", 0, 0x2000, CRC(3335a19b) SHA1(72eedfcc799ec4c7534fd7415de6631087ff6731) )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
ROM_LOAD16_WORD_SWAP( "epr-14870a.7", 0x00000, 0x20000, CRC(919d9b75) SHA1(27be79881cc9a2b5cf37e18f1e2d87251426b428) )
@@ -1351,11 +1351,11 @@ ROM_START( swa )
ROM_LOAD16_BYTE( "epr-16670.15", 0x200001, 0x80000, CRC(1e7ecabd) SHA1(62e8dd5d3a053426a1f3d94d15b04621d36d6a2c) )
ROM_LOAD( "epr-16668.5", 0xf80000, 0x80000, CRC(9e112425) SHA1(fc7be83b33b586780444e3426164e1cb5125f794) )
- ROM_RELOAD( 0x000000, 0x80000 )
- ROM_RELOAD( 0x080000, 0x80000 )
+ ROM_RELOAD( 0x000000, 0x80000 )
+ ROM_RELOAD( 0x080000, 0x80000 )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP)
+ ROM_LOAD( "315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP)
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
ROM_LOAD16_WORD_SWAP( "epr-16470.7", 0x000000, 0x020000, CRC(7da18cf7) SHA1(bd432d882d217277faee120e2577357a32eb4a6e) )
@@ -1399,11 +1399,11 @@ ROM_START( swaj )
ROM_LOAD16_BYTE( "epr-16469.15", 0x200001, 0x80000, CRC(6f281f7c) SHA1(6a9179e48d14838bb2a1a3f63fdd3a68ed009e03) )
ROM_LOAD( "epr-16467.5", 0xf80000, 0x80000, CRC(605068f5) SHA1(99d7e171ce3353477c282d7567dedb9947206f14) )
- ROM_RELOAD( 0x000000, 0x80000 )
- ROM_RELOAD( 0x080000, 0x80000 )
+ ROM_RELOAD( 0x000000, 0x80000 )
+ ROM_RELOAD( 0x080000, 0x80000 )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
+ ROM_LOAD( "315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
ROM_LOAD16_WORD_SWAP( "epr-16470.7", 0x000000, 0x020000, CRC(7da18cf7) SHA1(bd432d882d217277faee120e2577357a32eb4a6e) )
@@ -1447,10 +1447,10 @@ ROM_START( wingwar )
ROM_LOAD16_BYTE( "epr-16729.14", 0x200000, 0x80000, CRC(7edec2cc) SHA1(3e423a868ca7c8475fbb5bc1a10526e69d94d865) )
ROM_LOAD16_BYTE( "epr-16730.15", 0x200001, 0x80000, CRC(bab24dee) SHA1(26c95139c1aa7f34b6a5cce39e5bd1dd2ef0dd49) )
- ROM_LOAD( "epr16953.4", 0xfc0000, 0x20000, CRC(c821a920) SHA1(7fc9ea5d828aac664514fa6d38f708f1ffd26220) )
- ROM_RELOAD( 0x000000, 0x20000 )
- ROM_LOAD( "epr16952.5", 0xfe0000, 0x20000, CRC(03a3ecc5) SHA1(5c4aa221302b0a0800e1af99a41ab46fe4325184) )
- ROM_RELOAD( 0x020000, 0x20000 )
+ ROM_LOAD( "epr-16953.4", 0xfc0000, 0x20000, CRC(c821a920) SHA1(7fc9ea5d828aac664514fa6d38f708f1ffd26220) )
+ ROM_RELOAD( 0x000000, 0x20000 )
+ ROM_LOAD( "epr-16952.5", 0xfe0000, 0x20000, CRC(03a3ecc5) SHA1(5c4aa221302b0a0800e1af99a41ab46fe4325184) )
+ ROM_RELOAD( 0x020000, 0x20000 )
ROM_LOAD16_BYTE( "mpr-16738.6", 0x1000000, 0x80000, CRC(51518ffa) SHA1(e4674ddfed4205957b14e133c6fdf6454872f324) )
ROM_LOAD16_BYTE( "mpr-16737.7", 0x1000001, 0x80000, CRC(37b1379c) SHA1(98620c324268e1dd906c077ac8a8cd903b9de1f7) )
@@ -1460,20 +1460,20 @@ ROM_START( wingwar )
ROM_LOAD16_BYTE( "mpr-16733.11", 0x1200001, 0x80000, CRC(e105847b) SHA1(8489a6c91fd6d1e9ba81e8eaf36c514da30dccbe) )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
+ ROM_LOAD( "315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
- ROM_LOAD16_WORD_SWAP("epr-17126.7", 0x000000, 0x20000, CRC(50178e40) SHA1(fb01aecfbe4e90adc997de0d45a63c16ef353b37) )
- ROM_LOAD16_WORD_SWAP("epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
+ ROM_LOAD16_WORD_SWAP( "epr-17126.7", 0x000000, 0x20000, CRC(50178e40) SHA1(fb01aecfbe4e90adc997de0d45a63c16ef353b37) )
+ ROM_LOAD16_WORD_SWAP( "epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
ROM_RELOAD(0x80000, 0x20000)
ROM_REGION( 0x400000, M1AUDIO_MPCM1_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
- ROM_LOAD("mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
+ ROM_LOAD( "mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
+ ROM_LOAD( "mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
ROM_REGION( 0x400000, M1AUDIO_MPCM2_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
- ROM_LOAD("mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
+ ROM_LOAD( "mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
+ ROM_LOAD( "mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
ROM_REGION32_LE( 0x1000000, "polygons", 0 ) /* TGP model roms */
ROM_LOAD32_WORD( "mpr-16743.26", 0x000000, 0x200000, CRC(a710d33c) SHA1(1d0184545b34789ed511caaa25d57db3cd9a8e2f) )
@@ -1508,10 +1508,10 @@ ROM_START( wingwaru )
ROM_LOAD16_BYTE( "epr-16729.14", 0x200000, 0x80000, CRC(7edec2cc) SHA1(3e423a868ca7c8475fbb5bc1a10526e69d94d865) )
ROM_LOAD16_BYTE( "epr-16730.15", 0x200001, 0x80000, CRC(bab24dee) SHA1(26c95139c1aa7f34b6a5cce39e5bd1dd2ef0dd49) )
- ROM_LOAD( "epr-16951.4", 0xfc0000, 0x20000, BAD_DUMP CRC(8df5a798) SHA1(ef2756f237933ecf429dab0f362e572eb1965f4d) )
- ROM_RELOAD( 0x000000, 0x20000 )
+ ROM_LOAD( "epr-16951.4", 0xfc0000, 0x20000, CRC(fbe12d15) SHA1(07e572d20babc47c14b20af51c567c36b1b9c7a9) )
+ ROM_RELOAD( 0x000000, 0x20000 )
ROM_LOAD( "epr-16950.5", 0xfe0000, 0x20000, CRC(841e2195) SHA1(66f465aaf71955496e6f83335f7b836ad1d8c724) )
- ROM_RELOAD( 0x020000, 0x20000 )
+ ROM_RELOAD( 0x020000, 0x20000 )
ROM_LOAD16_BYTE( "mpr-16738.6", 0x1000000, 0x80000, CRC(51518ffa) SHA1(e4674ddfed4205957b14e133c6fdf6454872f324) )
ROM_LOAD16_BYTE( "mpr-16737.7", 0x1000001, 0x80000, CRC(37b1379c) SHA1(98620c324268e1dd906c077ac8a8cd903b9de1f7) )
@@ -1521,20 +1521,20 @@ ROM_START( wingwaru )
ROM_LOAD16_BYTE( "mpr-16733.11", 0x1200001, 0x80000, CRC(e105847b) SHA1(8489a6c91fd6d1e9ba81e8eaf36c514da30dccbe) )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
+ ROM_LOAD( "315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
- ROM_LOAD16_WORD_SWAP("epr-16751.7", 0x000000, 0x20000, CRC(23ba5ebc) SHA1(b98aab546c5e980baeedbada4e7472eb4c588260) )
- ROM_LOAD16_WORD_SWAP("epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
+ ROM_LOAD16_WORD_SWAP( "epr-16751.7", 0x000000, 0x20000, CRC(23ba5ebc) SHA1(b98aab546c5e980baeedbada4e7472eb4c588260) )
+ ROM_LOAD16_WORD_SWAP( "epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
ROM_RELOAD(0x80000, 0x20000)
ROM_REGION( 0x400000, M1AUDIO_MPCM1_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
- ROM_LOAD("mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
+ ROM_LOAD( "mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
+ ROM_LOAD( "mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
ROM_REGION( 0x400000, M1AUDIO_MPCM2_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
- ROM_LOAD("mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
+ ROM_LOAD( "mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
+ ROM_LOAD( "mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
ROM_REGION32_LE( 0x1000000, "polygons", 0 ) /* TGP model roms */
ROM_LOAD32_WORD( "mpr-16743.26", 0x000000, 0x200000, CRC(a710d33c) SHA1(1d0184545b34789ed511caaa25d57db3cd9a8e2f) )
@@ -1561,9 +1561,9 @@ ROM_START( wingwarj )
ROM_LOAD16_BYTE( "epr-16730.15", 0x200001, 0x80000, CRC(bab24dee) SHA1(26c95139c1aa7f34b6a5cce39e5bd1dd2ef0dd49) )
ROM_LOAD( "epr-16728.4", 0xfc0000, 0x20000, CRC(194d58ff) SHA1(281201cbb9bb148a06fe88edeccf680f837dcc10) )
- ROM_RELOAD( 0x000000, 0x20000 )
+ ROM_RELOAD( 0x000000, 0x20000 )
ROM_LOAD( "epr-16727.5", 0xfe0000, 0x20000, CRC(430380eb) SHA1(25bd81a69a9b4cdc644f912283b65b3eab988327) )
- ROM_RELOAD( 0x020000, 0x20000 )
+ ROM_RELOAD( 0x020000, 0x20000 )
ROM_LOAD16_BYTE( "mpr-16738.6", 0x1000000, 0x80000, CRC(51518ffa) SHA1(e4674ddfed4205957b14e133c6fdf6454872f324) )
ROM_LOAD16_BYTE( "mpr-16737.7", 0x1000001, 0x80000, CRC(37b1379c) SHA1(98620c324268e1dd906c077ac8a8cd903b9de1f7) )
@@ -1573,20 +1573,20 @@ ROM_START( wingwarj )
ROM_LOAD16_BYTE( "mpr-16733.11", 0x1200001, 0x80000, CRC(e105847b) SHA1(8489a6c91fd6d1e9ba81e8eaf36c514da30dccbe) )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
+ ROM_LOAD( "315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
- ROM_LOAD16_WORD_SWAP("epr-16751.7", 0x000000, 0x20000, CRC(23ba5ebc) SHA1(b98aab546c5e980baeedbada4e7472eb4c588260) )
- ROM_LOAD16_WORD_SWAP("epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
+ ROM_LOAD16_WORD_SWAP( "epr-16751.7", 0x000000, 0x20000, CRC(23ba5ebc) SHA1(b98aab546c5e980baeedbada4e7472eb4c588260) )
+ ROM_LOAD16_WORD_SWAP( "epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
ROM_RELOAD(0x80000, 0x20000)
ROM_REGION( 0x400000, M1AUDIO_MPCM1_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
- ROM_LOAD("mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
+ ROM_LOAD( "mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
+ ROM_LOAD( "mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
ROM_REGION( 0x400000, M1AUDIO_MPCM2_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
- ROM_LOAD("mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
+ ROM_LOAD( "mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
+ ROM_LOAD( "mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
ROM_REGION32_LE( 0x1000000, "polygons", 0 ) /* TGP model roms */
ROM_LOAD32_WORD( "mpr-16743.26", 0x000000, 0x200000, CRC(a710d33c) SHA1(1d0184545b34789ed511caaa25d57db3cd9a8e2f) )
@@ -1615,32 +1615,32 @@ ROM_START( wingwar360 )
ROM_LOAD16_BYTE( "epr-16730.15", 0x200001, 0x80000, CRC(bab24dee) SHA1(26c95139c1aa7f34b6a5cce39e5bd1dd2ef0dd49) )
ROM_LOAD( "epr-17052.4", 0xfc0000, 0x20000, CRC(0f4743e7) SHA1(cc47fd1d25808728ed05d95d510733b8bd011b41) )
- ROM_RELOAD( 0x000000, 0x20000 )
+ ROM_RELOAD( 0x000000, 0x20000 )
ROM_LOAD( "epr-17053.5", 0xfe0000, 0x20000, CRC(83af2415) SHA1(46dfee9db95171a3942cd32c851ec75c3d9e03da) )
- ROM_RELOAD( 0x020000, 0x20000 )
+ ROM_RELOAD( 0x020000, 0x20000 )
- ROM_LOAD16_BYTE( "ic6_17056.bin", 0x1000000, 0x80000, CRC(5216de4d) SHA1(1463311d3f96ca7c46b8f676ee3963caddeec9e2) )
- ROM_LOAD16_BYTE( "ic7_17057.bin", 0x1000001, 0x80000, CRC(b21aa2db) SHA1(861e637b5ae9b2d7fe6d09a7e788a6a3ff09af6e) )
+ ROM_LOAD16_BYTE( "epr-17056.6", 0x1000000, 0x80000, CRC(5216de4d) SHA1(1463311d3f96ca7c46b8f676ee3963caddeec9e2) )
+ ROM_LOAD16_BYTE( "epr-17057.7", 0x1000001, 0x80000, CRC(b21aa2db) SHA1(861e637b5ae9b2d7fe6d09a7e788a6a3ff09af6e) )
ROM_LOAD16_BYTE( "mpr-16736.8", 0x1100000, 0x80000, CRC(10b6a025) SHA1(7a4f624ceb7c0b92044a5db8ff55440562ef836b) )
ROM_LOAD16_BYTE( "mpr-16735.9", 0x1100001, 0x80000, CRC(c82fd198) SHA1(d9e53ae1e14dfc8e84a14c0026ef0b904863bb1b) )
ROM_LOAD16_BYTE( "mpr-16734.10", 0x1200000, 0x80000, CRC(f76371c1) SHA1(0ff082db3877383d0dd977dc60c932b725e3d164) )
ROM_LOAD16_BYTE( "mpr-16733.11", 0x1200001, 0x80000, CRC(e105847b) SHA1(8489a6c91fd6d1e9ba81e8eaf36c514da30dccbe) )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
+ ROM_LOAD( "315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
- ROM_LOAD16_WORD_SWAP("epr-17126.7", 0x000000, 0x20000, CRC(50178e40) SHA1(fb01aecfbe4e90adc997de0d45a63c16ef353b37) )
- ROM_LOAD16_WORD_SWAP("epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
+ ROM_LOAD16_WORD_SWAP( "epr-17126.7", 0x000000, 0x20000, CRC(50178e40) SHA1(fb01aecfbe4e90adc997de0d45a63c16ef353b37) )
+ ROM_LOAD16_WORD_SWAP( "epr-16752.8", 0x020000, 0x20000, CRC(6541c48f) SHA1(9341eff160e31a8574b9545fafc1c4059323fa0c) )
ROM_RELOAD(0x80000, 0x20000)
ROM_REGION( 0x400000, M1AUDIO_MPCM1_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
- ROM_LOAD("mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
+ ROM_LOAD( "mpr-16753.32", 0x000000, 0x200000, CRC(324a8333) SHA1(960342e08db637c6f72615d49cffd9fb0889620b) )
+ ROM_LOAD( "mpr-16754.33", 0x200000, 0x200000, CRC(144f3cf5) SHA1(d2f8cc9086affbbc5ef2195272200230f724e5d1) )
ROM_REGION( 0x400000, M1AUDIO_MPCM2_REGION, 0 ) /* Samples */
- ROM_LOAD("mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
- ROM_LOAD("mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
+ ROM_LOAD( "mpr-16755.4", 0x000000, 0x200000, CRC(4baaf878) SHA1(661d4ea9be6a4952852d0ef94becee7ed42bf4a1) )
+ ROM_LOAD( "mpr-16756.5", 0x200000, 0x200000, CRC(d9c40672) SHA1(83e6f1156b30888d3a00103f079dc74f4fca8446) )
ROM_REGION32_LE( 0x1000000, "polygons", 0 ) /* TGP model roms */
ROM_LOAD32_WORD( "mpr-16743.26", 0x000000, 0x200000, CRC(a710d33c) SHA1(1d0184545b34789ed511caaa25d57db3cd9a8e2f) )
@@ -1660,8 +1660,8 @@ ROM_START( wingwar360 )
// Dumper's note: Video & Drive is the control board in the attendants' tower, same hardware as G-Loc R360 with the two program roms being the only difference.
ROM_REGION( 0x400000, "controlboard", 0 )
- ROM_LOAD("ic22_18851.bin", 0x00000, 0x20000, CRC(85f75bd7) SHA1(43cc8f8c81631d71b661e55e15f3fe8803a8a7e9) )
- ROM_LOAD("ic67_18850.bin", 0x20000, 0x08000, CRC(45a3e9fc) SHA1(bf2d1a7acc35b72a62551bfbb55e5058d6fd6d5c) )
+ ROM_LOAD( "epr-18851.ic22", 0x00000, 0x20000, CRC(85f75bd7) SHA1(43cc8f8c81631d71b661e55e15f3fe8803a8a7e9) )
+ ROM_LOAD( "epr-18850.ic67", 0x20000, 0x08000, CRC(45a3e9fc) SHA1(bf2d1a7acc35b72a62551bfbb55e5058d6fd6d5c) )
ROM_END
ROM_START( netmerc )
@@ -1679,7 +1679,7 @@ ROM_START( netmerc )
ROM_LOAD16_BYTE( "epr-18127.ic11", 0x1200001, 0x80000, CRC(d307a4ca) SHA1(5555235f740c1b09f6e1587d0fceb35b23d4a8a8) )
ROM_REGION32_LE( 0x2000, "tgp_copro", 0)
- ROM_LOAD("315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
+ ROM_LOAD( "315-5711.bin", 0, 0x2000, CRC(c5ddb8fc) SHA1(9e21d3a07ffa315e0139483b664e3fa283ef4e06) BAD_DUMP )
ROM_REGION( 0xc0000, M1AUDIO_CPU_REGION, ROMREGION_BE|ROMREGION_16BIT ) /* 68K code */
ROM_LOAD16_WORD_SWAP( "epr-18121.ic7", 0x00000, 0x80000, CRC(113285b5) SHA1(5d060cee41e8d6a4a918f890c2d169d87dbcad79) )
diff --git a/src/mame/drivers/saitek_leonardo.cpp b/src/mame/drivers/saitek_leonardo.cpp
index 95009b8cd0c..09cef526c7f 100644
--- a/src/mame/drivers/saitek_leonardo.cpp
+++ b/src/mame/drivers/saitek_leonardo.cpp
@@ -53,6 +53,7 @@ TODO:
#include "bus/saitek_osa/expansion.h"
#include "cpu/m6800/m6801.h"
+#include "machine/input_merger.h"
#include "machine/sensorboard.h"
#include "sound/spkrdev.h"
#include "video/pwm.h"
@@ -73,6 +74,7 @@ public:
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_expansion(*this, "exp"),
+ m_stb(*this, "stb"),
m_board(*this, "board"),
m_display(*this, "display"),
m_dac(*this, "dac"),
@@ -90,6 +92,7 @@ private:
// devices/pointers
required_device<hd6303y_cpu_device> m_maincpu;
required_device<saitekosa_expansion_device> m_expansion;
+ required_device<input_merger_device> m_stb;
required_device<sensorboard_device> m_board;
required_device<pwm_display_device> m_display;
optional_device<speaker_sound_device> m_dac;
@@ -102,7 +105,6 @@ private:
void leds_w(u8 data);
u8 unk_r();
void unk_w(u8 data);
- void exp_stb_w(int state);
void exp_rts_w(int state);
u8 p2_r();
@@ -166,15 +168,9 @@ void leo_state::unk_w(u8 data)
// ?
}
-void leo_state::exp_stb_w(int state)
-{
- // STB-P to P5 IS
- m_maincpu->set_input_line(M6801_IS_LINE, state ? CLEAR_LINE : ASSERT_LINE);
-}
-
void leo_state::exp_rts_w(int state)
{
- // NAND with ACK-P? (not used by module)
+ // NAND with ACK-P (not used by module)
}
@@ -213,7 +209,8 @@ void leo_state::p5_w(u8 data)
// d2: expansion NMI-P
m_expansion->nmi_w(BIT(data, 2));
- // d3: NAND with STB-P?
+ // d3: NAND with STB-P
+ m_stb->in_w<1>(BIT(data, 3));
// d5: expansion ACK-P
m_expansion->ack_w(BIT(data, 5));
@@ -364,6 +361,9 @@ void leo_state::leonardo(machine_config &config)
m_maincpu->in_p6_cb().set(FUNC(leo_state::p6_r));
m_maincpu->out_p6_cb().set(FUNC(leo_state::p6_w));
+ INPUT_MERGER_ANY_LOW(config, m_stb);
+ m_stb->output_handler().set_inputline(m_maincpu, M6801_IS_LINE);
+
config.set_maximum_quantum(attotime::from_hz(6000));
SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
@@ -380,7 +380,7 @@ void leo_state::leonardo(machine_config &config)
// expansion module
SAITEKOSA_EXPANSION(config, m_expansion, saitekosa_expansion_modules);
- m_expansion->stb_handler().set(FUNC(leo_state::exp_stb_w));
+ m_expansion->stb_handler().set(m_stb, FUNC(input_merger_device::in_w<0>));
m_expansion->rts_handler().set(FUNC(leo_state::exp_rts_w));
}
diff --git a/src/mame/drivers/saitek_renaissance.cpp b/src/mame/drivers/saitek_renaissance.cpp
index 83cd1d26bbb..09fcabc6878 100644
--- a/src/mame/drivers/saitek_renaissance.cpp
+++ b/src/mame/drivers/saitek_renaissance.cpp
@@ -33,6 +33,7 @@ TODO:
#include "bus/saitek_osa/expansion.h"
#include "cpu/m6800/m6801.h"
+#include "machine/input_merger.h"
#include "machine/sensorboard.h"
#include "sound/spkrdev.h"
#include "video/pwm.h"
@@ -55,6 +56,7 @@ public:
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_expansion(*this, "exp"),
+ m_stb(*this, "stb"),
m_board(*this, "board"),
m_display(*this, "display"),
m_lcd_pwm(*this, "lcd_pwm"),
@@ -76,6 +78,7 @@ private:
// devices/pointers
required_device<hd6303y_cpu_device> m_maincpu;
required_device<saitekosa_expansion_device> m_expansion;
+ required_device<input_merger_device> m_stb;
required_device<sensorboard_device> m_board;
required_device<pwm_display_device> m_display;
required_device<pwm_display_device> m_lcd_pwm;
@@ -94,7 +97,6 @@ private:
void leds_w(u8 data);
void control_w(u8 data);
u8 control_r();
- void exp_stb_w(int state);
void exp_rts_w(int state);
u8 p2_r();
@@ -189,15 +191,9 @@ u8 ren_state::control_r()
return 0;
}
-void ren_state::exp_stb_w(int state)
-{
- // STB-P to P5 IS
- m_maincpu->set_input_line(M6801_IS_LINE, state ? CLEAR_LINE : ASSERT_LINE);
-}
-
void ren_state::exp_rts_w(int state)
{
- // NAND with ACK-P? (not used by module)
+ // NAND with ACK-P (not used by module)
}
@@ -237,7 +233,8 @@ void ren_state::p5_w(u8 data)
// d1: expansion NMI-P
m_expansion->nmi_w(BIT(data, 1));
- // d3: NAND with STB-P?
+ // d3: NAND with STB-P
+ m_stb->in_w<1>(BIT(data, 3));
// d5: expansion ACK-P
m_expansion->ack_w(BIT(data, 5));
@@ -354,6 +351,9 @@ void ren_state::ren(machine_config &config)
m_maincpu->in_p6_cb().set(FUNC(ren_state::p6_r));
m_maincpu->out_p6_cb().set(FUNC(ren_state::p6_w));
+ INPUT_MERGER_ANY_LOW(config, m_stb);
+ m_stb->output_handler().set_inputline(m_maincpu, M6801_IS_LINE);
+
config.set_maximum_quantum(attotime::from_hz(6000));
SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
@@ -380,7 +380,7 @@ void ren_state::ren(machine_config &config)
// expansion module
SAITEKOSA_EXPANSION(config, m_expansion, saitekosa_expansion_modules);
- m_expansion->stb_handler().set(FUNC(ren_state::exp_stb_w));
+ m_expansion->stb_handler().set(m_stb, FUNC(input_merger_device::in_w<0>));
m_expansion->rts_handler().set(FUNC(ren_state::exp_rts_w));
}
diff --git a/src/mame/drivers/snowbros.cpp b/src/mame/drivers/snowbros.cpp
index 0773df4644e..558dde3e9fb 100644
--- a/src/mame/drivers/snowbros.cpp
+++ b/src/mame/drivers/snowbros.cpp
@@ -664,6 +664,23 @@ static INPUT_PORTS_START( snowbroj )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
INPUT_PORTS_END
+static INPUT_PORTS_START( ballboy3p )
+ PORT_INCLUDE(snowbros)
+
+ PORT_MODIFY("DSW1") // on the PCB in place of the dips there's the plug for the controls of the 3rd player
+ PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3)
+ PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
+ PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3)
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+
+ PORT_MODIFY("SYSTEM")
+ PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_START3 )
+INPUT_PORTS_END
+
static INPUT_PORTS_START( honeydol )
PORT_START("DSW1")
PORT_DIPNAME( 0x0003, 0x0003, DEF_STR( Coinage ) )
@@ -2766,6 +2783,27 @@ ROM_START( ballboy )
ROM_END
+ROM_START( ballboy3p ) //PCB etched JOYCUS10 (or JOYCU510) 2081627 (0, 6 and 8 aren't clearly readable)
+ ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
+ ROM_LOAD16_BYTE( "ur4", 0x00000, 0x20000, CRC(32153d8f) SHA1(1fa698b93507fb775dfff6da8701ab65c986cac5) )
+ ROM_LOAD16_BYTE( "ur3", 0x00001, 0x20000, CRC(4d462a75) SHA1(30a84a618bea5c64201329d02847382c2d0c84ba) )
+
+ // the sound is driven by an MCU
+ ROM_REGION( 0x10000, "cpu2", 0 )
+ ROM_LOAD( "sound.mcu", 0x00000, 0x10000 , NO_DUMP )
+
+ ROM_REGION( 0x80000, "gfx1", 0 )
+ ROM_LOAD( "ua5", 0x000000, 0x80000, CRC(fc72011f) SHA1(f1f10b34fd3365c6542299bd0224dad926d650b4) ) // 16x16 tiles
+
+ ROM_REGION( 0x400000, "gfx2", 0 ) // 16x16 BG Tiles
+ ROM_LOAD( "un7", 0x000000, 0x400000, CRC(fe427e9d) SHA1(6932ad18b6807af860f8430e2a00e959d6c36a23) )
+
+ ROM_REGION( 0x100000, "oki", 0 ) // OKIM6295 samples
+ ROM_LOAD( "us5", 0x00000, 0x20000, CRC(7c6368ef) SHA1(53393c570c605f7582b61c630980041e2ed32e2d) ) // only ROM identical to the 2 player version
+ ROM_CONTINUE(0x80000,0x60000)
+ROM_END
+
+
/*
Information from Korean arcade gaming magazine
@@ -2912,6 +2950,13 @@ void snowbros_state::init_snowbro3()
save_item(NAME(m_sb3_music));
}
+void snowbros_state::init_ballboy3p()
+{
+ init_snowbro3();
+
+ m_maincpu->space(AS_PROGRAM).unmap_write(0x400000, 0x400001); // unmap flipscreen as the DSW has been removed in favor of the controls for the 3rd player
+}
+
uint16_t snowbros_state::_3in1_read()
{
return 0x000a;
@@ -3028,9 +3073,9 @@ GAME( 1996, multi96, twinadv, twinadv, twinadv, snowbros_state, empty_i
// The Korean games database shows an earlier version of this called Ball Boy with a different title screen to the version of Ball Boy we have
// http://mamedev.emulab.it/undumped/images/Ballboy.jpg
// it is possible this 'ball boy' is the original bootleg, with snwobro3 being a hack of that, and the ballboy set we have a further hack of that
-// there is also a later 2004 version with 3 player support
// these use an MCU to drive the sound
-GAME( 2002, snowbro3, 0, snowbro3, snowbroj, snowbros_state, init_snowbro3, ROT0, "Syrmex", "Snow Brothers 3 - Magical Adventure", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // hacked from SnowBros code but released as an original game
-GAME( 2003, ballboy, snowbro3, snowbro3, snowbroj, snowbros_state, init_snowbro3, ROT0, "bootleg", "Ball Boy", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 2002, snowbro3, 0, snowbro3, snowbroj, snowbros_state, init_snowbro3, ROT0, "Syrmex", "Snow Brothers 3 - Magical Adventure", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // hacked from SnowBros code but released as an original game
+GAME( 2003, ballboy, snowbro3, snowbro3, snowbroj, snowbros_state, init_snowbro3, ROT0, "bootleg", "Ball Boy (2 players)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 2004, ballboy3p, snowbro3, snowbro3, ballboy3p, snowbros_state, init_ballboy3p, ROT0, "bootleg", "Ball Boy (3 players)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
// protection appears to handle the sound, should check if it's just a block of code that is conditionally executed like some of the Semicom titles.
-GAME( 1999, yutnori, 0, yutnori, yutnori, snowbros_state, init_yutnori, ROT0, "Nunal", "Puzzle Yutnori (Korea)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND ) // Nunal is apparently Korean slang for Eyeball, hence the logo. Some places report 'JCC Soft' as the manufacturer
+GAME( 1999, yutnori, 0, yutnori, yutnori, snowbros_state, init_yutnori, ROT0, "Nunal", "Puzzle Yutnori (Korea)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND ) // Nunal is apparently Korean slang for Eyeball, hence the logo. Some places report 'JCC Soft' as the manufacturer
diff --git a/src/mame/drivers/xerox820.cpp b/src/mame/drivers/xerox820.cpp
index 9f17964ed56..04d3a8fedff 100644
--- a/src/mame/drivers/xerox820.cpp
+++ b/src/mame/drivers/xerox820.cpp
@@ -64,45 +64,6 @@
/* Read/Write Handlers */
-void xerox820_state::bankswitch(int bank)
-{
- address_space &program = m_maincpu->space(AS_PROGRAM);
- uint8_t *ram = m_ram->pointer();
-
- if (bank)
- {
- /* ROM */
- program.install_rom(0x0000, 0x0fff, m_rom->base());
- program.unmap_readwrite(0x1000, 0x1fff);
- program.install_ram(0x3000, 0x3fff, m_video_ram);
- }
- else
- {
- /* RAM */
- program.install_ram(0x0000, 0x3fff, ram);
- }
-}
-
-void xerox820ii_state::bankswitch(int bank)
-{
- address_space &program = m_maincpu->space(AS_PROGRAM);
- uint8_t *ram = m_ram->pointer();
-
- if (bank)
- {
- /* ROM */
- program.install_rom(0x0000, 0x1fff, m_rom->base());
- program.unmap_readwrite(0x2000, 0x2fff);
- program.install_ram(0x3000, 0x3fff, m_video_ram);
- program.unmap_readwrite(0x4000, 0xbfff);
- }
- else
- {
- /* RAM */
- program.install_ram(0x0000, 0xbfff, ram);
- }
-}
-
uint8_t xerox820_state::fdc_r(offs_t offset)
{
return m_fdc->read(offset) ^ 0xff;
@@ -175,7 +136,10 @@ void xerox820ii_state::sync_w(offs_t offset, uint8_t data)
void xerox820_state::xerox820_mem(address_map &map)
{
map.unmap_value_high();
- map(0x3000, 0x3fff).ram().share("video_ram");
+ map(0x0000, 0x3fff).view(m_view);
+ m_view[0](0x0000, 0x3fff).ram();
+ m_view[1](0x0000, 0x0fff).rom().region(Z80_TAG, 0);
+ m_view[1](0x3000, 0x3fff).ram().share("video_ram");
map(0x4000, 0xffff).ram();
}
@@ -194,7 +158,10 @@ void xerox820_state::xerox820_io(address_map &map)
void xerox820ii_state::xerox820ii_mem(address_map &map)
{
map.unmap_value_high();
- map(0x3000, 0x3fff).ram().share("video_ram");
+ map(0x0000, 0xbfff).view(m_view);
+ m_view[0](0x0000, 0xbfff).ram();
+ m_view[1](0x0000, 0x1fff).rom().region(Z80_TAG, 0);
+ m_view[1](0x3000, 0x3fff).ram().share("video_ram");
map(0xc000, 0xffff).ram();
}
@@ -217,6 +184,9 @@ void xerox820ii_state::xerox168_mem(address_map &map)
void xerox820_state::mk83_mem(address_map &map)
{
map.unmap_value_high();
+ map(0x0000, 0x2fff).view(m_view);
+ m_view[0](0x0000, 0x2fff).ram();
+ m_view[1](0x0000, 0x0fff).rom().region(Z80_TAG, 0);
map(0x3000, 0x6fff).ram();
map(0x7000, 0x7fff).ram().share("video_ram");
map(0x8000, 0xffff).ram();
@@ -312,7 +282,7 @@ void xerox820_state::kbpio_pa_w(uint8_t data)
m_ncset2 = !BIT(data, 6);
/* bank switching */
- bankswitch(BIT(data, 7));
+ m_view.select(BIT(data, 7));
}
void bigboard_state::kbpio_pa_w(uint8_t data)
@@ -413,7 +383,7 @@ QUICKLOAD_LOAD_MEMBER(xerox820_state::quickload_cb)
if (image.length() >= 0xfd00)
return image_init_result::FAIL;
- bankswitch(0);
+ m_view.select(0);
/* Avoid loading a program if CP/M-80 is not in memory */
if ((prog_space.read_byte(0) != 0xc3) || (prog_space.read_byte(5) != 0xc3))
@@ -544,14 +514,14 @@ void xerox820_state::machine_start()
void xerox820_state::machine_reset()
{
- bankswitch(1);
+ m_view.select(1);
m_fdc->reset();
}
void bigboard_state::machine_reset()
{
- bankswitch(1);
+ m_view.select(1);
/* bigboard has a one-pulse output to drive a user-supplied beeper */
m_beeper->set_state(0);
@@ -561,7 +531,7 @@ void bigboard_state::machine_reset()
void xerox820ii_state::machine_reset()
{
- bankswitch(1);
+ m_view.select(1);
m_fdc->reset();
@@ -684,9 +654,6 @@ void xerox820_state::xerox820(machine_config &config)
XEROX_820_KEYBOARD(config, m_kb, 0);
m_kb->kbstb_wr_callback().set(m_kbpio, FUNC(z80pio_device::strobe_b));
- /* internal ram */
- RAM(config, m_ram).set_default_size("64K");
-
// software lists
SOFTWARE_LIST(config, "flop_list").set_original("xerox820");
QUICKLOAD(config, "quickload", "com,cpm", attotime::from_seconds(3)).set_load_callback(FUNC(xerox820_state::quickload_cb));
@@ -793,9 +760,6 @@ void xerox820ii_state::xerox820ii(machine_config &config)
INPUT_BUFFER(config, "sasi_data_in");
INPUT_BUFFER(config, "sasi_ctrl_in");
- /* internal ram */
- RAM(config, m_ram).set_default_size("64K");
-
// software lists
SOFTWARE_LIST(config, "flop_list").set_original("xerox820ii");
QUICKLOAD(config, "quickload", "com,cpm", attotime::from_seconds(3)).set_load_callback(FUNC(xerox820_state::quickload_cb));
@@ -808,7 +772,7 @@ void xerox820ii_state::xerox168(machine_config &config)
i8086.set_addrmap(AS_PROGRAM, &xerox820ii_state::xerox168_mem);
/* internal ram */
- m_ram->set_default_size("192K").set_extra_options("320K");
+ RAM(config, m_ram).set_default_size("192K").set_extra_options("320K");
}
void xerox820_state::mk83(machine_config & config)
diff --git a/src/mame/drivers/ympsr60.cpp b/src/mame/drivers/ympsr60.cpp
index 42ee77a8855..f5c57f639e1 100644
--- a/src/mame/drivers/ympsr60.cpp
+++ b/src/mame/drivers/ympsr60.cpp
@@ -12,7 +12,7 @@
Service manual: https://elektrotanya.com/yamaha_psr-70_sm.pdf/download.html
CPU: Z80 @ 6 MHz
- Sound: YM3806 "OPQ" FM @ 3.58 MHz + YM2154 "RYP" sample playback chip for drums
+ Sound: YM3533 "OPQ" FM @ 3.58 MHz + YM2154 "RYP" sample playback chip for drums
Panel and keyboard I/O: 82C55A PPI and Yamaha IG14330 "DRVIF"
MIDI I/O: HD6350 ACIA, baud rate clock is 500 kHz
@@ -59,7 +59,7 @@ public:
psr60_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
- m_ym3806(*this, "ym3806"),
+ m_ym3533(*this, "ym3533"),
m_ppi(*this, "ppi"),
m_acia(*this, "acia"),
m_rom2bank(*this, "rom2bank")
@@ -73,7 +73,7 @@ protected:
private:
required_device<z80_device> m_maincpu;
- required_device<ym3806_device> m_ym3806;
+ required_device<ym3533_device> m_ym3533;
required_device<i8255_device> m_ppi;
required_device<acia6850_device> m_acia;
required_memory_bank m_rom2bank;
@@ -89,7 +89,7 @@ private:
WRITE_LINE_MEMBER(write_acia_clock) { m_acia->write_txc(state); m_acia->write_rxc(state); }
WRITE_LINE_MEMBER(acia_irq_w) { m_acia_irq = state; recalc_irqs(); }
- WRITE_LINE_MEMBER(ym_irq_w) { m_ym_irq = state; recalc_irqs(); printf("YM IRQ %d\n", state); }
+ WRITE_LINE_MEMBER(ym_irq_w) { m_ym_irq = state; recalc_irqs(); }
};
@@ -97,7 +97,7 @@ void psr60_state::psr60_map(address_map &map)
{
map(0x0000, 0x7fff).rom().region("rom1", 0);
map(0x8000, 0xbfff).bankr("rom2bank");
- map(0xc000, 0xc0ff).rw(m_ym3806, FUNC(ym3806_device::read), FUNC(ym3806_device::write));
+ map(0xc000, 0xc0ff).rw(m_ym3533, FUNC(ym3533_device::read), FUNC(ym3533_device::write));
map(0xe000, 0xffff).ram(); // work RAM
}
@@ -159,10 +159,10 @@ void psr60_state::psr60(machine_config &config)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
- YM3806(config, m_ym3806, 3.579545_MHz_XTAL);
- m_ym3806->irq_handler().set(FUNC(psr60_state::ym_irq_w));
- m_ym3806->add_route(0, "lspeaker", 1.0);
- m_ym3806->add_route(1, "rspeaker", 1.0);
+ YM3533(config, m_ym3533, 3.579545_MHz_XTAL);
+ m_ym3533->irq_handler().set(FUNC(psr60_state::ym_irq_w));
+ m_ym3533->add_route(0, "lspeaker", 1.0);
+ m_ym3533->add_route(1, "rspeaker", 1.0);
}
ROM_START( psr60 )
diff --git a/src/mame/drivers/ymtx81z.cpp b/src/mame/drivers/ymtx81z.cpp
index 61841a7f385..1700eca1320 100644
--- a/src/mame/drivers/ymtx81z.cpp
+++ b/src/mame/drivers/ymtx81z.cpp
@@ -7,13 +7,14 @@
****************************************************************************/
#include "emu.h"
-//#include "bus/midi/midi.h"
+
+#include "bus/midi/midi.h"
#include "cpu/m6800/m6801.h"
#include "machine/clock.h"
#include "machine/nvram.h"
#include "sound/ymopz.h"
#include "video/hd44780.h"
-#include "bus/midi/midi.h"
+
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
@@ -58,8 +59,8 @@ HD44780_PIXEL_UPDATE(ymtx81z_state::lcd_pixel_update)
void ymtx81z_state::palette_init(palette_device &palette)
{
palette.set_pen_color(0, rgb_t(0x00, 0x00, 0x00)); // background
- palette.set_pen_color(1, rgb_t(0xd8, 0xff, 0x18)); // lcd pixel on
- palette.set_pen_color(2, rgb_t(0xd8/10, 0xff/10, 0x18/10)); // lcd pixel off
+ palette.set_pen_color(1, rgb_t(0xff, 0xff, 0xff)); // lcd pixel on
+ palette.set_pen_color(2, rgb_t(0x18, 0x18, 0x18)); // lcd pixel off
}
void ymtx81z_state::machine_start()
diff --git a/src/mame/includes/snowbros.h b/src/mame/includes/snowbros.h
index 04b247deca7..c81a9bee613 100644
--- a/src/mame/includes/snowbros.h
+++ b/src/mame/includes/snowbros.h
@@ -44,6 +44,7 @@ public:
void init_pzlbreak();
void init_snowbro3();
+ void init_ballboy3p();
void init_cookbib3();
void init_4in1boot();
void init_3in1semi();
diff --git a/src/mame/includes/xerox820.h b/src/mame/includes/xerox820.h
index e5e9c9c3f81..850a7c7a9c2 100644
--- a/src/mame/includes/xerox820.h
+++ b/src/mame/includes/xerox820.h
@@ -65,6 +65,7 @@ public:
m_rom(*this, Z80_TAG),
m_char_rom(*this, "chargen"),
m_video_ram(*this, "video_ram"),
+ m_view(*this, "view"),
m_fdc_irq(0),
m_fdc_drq(0),
m_8n5(0),
@@ -104,7 +105,7 @@ protected:
required_device<z80ctc_device> m_ctc;
required_device<z80sio_device> m_sio;
required_device<wd_fdc_device_base> m_fdc;
- required_device<ram_device> m_ram;
+ optional_device<ram_device> m_ram;
required_device<palette_device> m_palette;
required_device<floppy_connector> m_floppy0;
required_device<floppy_connector> m_floppy1;
@@ -112,8 +113,8 @@ protected:
required_memory_region m_rom;
required_memory_region m_char_rom;
required_shared_ptr<uint8_t> m_video_ram;
+ memory_view m_view;
- virtual void bankswitch(int bank);
void update_nmi();
/* video state */
@@ -181,8 +182,6 @@ public:
protected:
virtual void machine_reset() override;
- void bankswitch(int bank) override;
-
required_device<speaker_sound_device> m_speaker;
required_device<scsi_port_device> m_sasibus;
};
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 5d39cad5068..7b8de7b5c2e 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -38478,6 +38478,7 @@ crystalca // 1998 JCD srl
3in1semi // (c) 1998 SemiCom
4in1boot // (c) 2002 KISoft (includes hacks of Semicom games + Snowbros)
ballboy // bootleg
+ballboy3p // bootleg
cookbib2 // (c) 1996 SemiCom
cookbib2a // (c) 1996 SemiCom
cookbib2b // (c) 1996 SemiCom
diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp
index bff08afb600..7cd7c2ad7f0 100644
--- a/src/tools/floptool.cpp
+++ b/src/tools/floptool.cpp
@@ -15,263 +15,16 @@
#include <cassert>
#include <map>
-#include "../emu/emucore.h"
+#include "image_handler.h"
#include "corestr.h"
-#include "osdcomm.h"
-
-using u8 = uint8_t;
-using u16 = uint16_t;
-using u32 = uint32_t;
-
-#include "formats/all.h"
-#include "formats/fs_unformatted.h"
-#include "formats/fsblk_vec.h"
-
-emu_fatalerror::emu_fatalerror(util::format_argument_pack<std::ostream> const &args)
- : emu_fatalerror(0, args)
-{
-}
-
-emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack<std::ostream> const &args)
- : m_text(util::string_format(args))
- , m_code(_exitcode)
-{
-}
-
-struct fs_info {
- const filesystem_manager_t *m_manager;
- floppy_format_type m_type;
- u32 m_image_size;
- const char *m_name;
- u32 m_key;
- const char *m_description;
-
- fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) :
- m_manager(manager),
- m_type(type),
- m_image_size(image_size),
- m_name(name),
- m_key(0),
- m_description(description)
- {}
-
- fs_info(const char *name, u32 key, const char *description) :
- m_manager(nullptr),
- m_type(nullptr),
- m_image_size(0),
- m_name(name),
- m_key(key),
- m_description(description)
- {}
-};
-
-struct iofile_ram {
- std::vector<u8> *data;
- int64_t pos;
-};
-
-static void ram_closeproc(void *file)
-{
- auto f = (iofile_ram *)file;
- delete f;
-}
-
-static int ram_seekproc(void *file, int64_t offset, int whence)
-{
- auto f = (iofile_ram *)file;
- switch(whence) {
- case SEEK_SET: f->pos = offset; break;
- case SEEK_CUR: f->pos += offset; break;
- case SEEK_END: f->pos = f->data->size() + offset; break;
- }
-
- if(whence == SEEK_CUR)
- f->pos = std::max<int64_t>(f->pos, 0);
- else
- f->pos = std::clamp<int64_t>(f->pos, 0, f->data->size());
- return 0;
-}
-
-static size_t ram_readproc(void *file, void *buffer, size_t length)
-{
- auto f = (iofile_ram *)file;
- size_t l = std::min<std::common_type_t<size_t, int64_t> >(length, f->data->size() - f->pos);
- memcpy(buffer, f->data->data() + f->pos, l);
- return l;
-}
-
-static size_t ram_writeproc(void *file, const void *buffer, size_t length)
-{
- auto f = (iofile_ram *)file;
- size_t l = std::max<std::common_type_t<size_t, int64_t> >(f->pos + length, f->data->size());
- f->data->resize(l);
- memcpy(f->data->data() + f->pos, buffer, length);
- return length;
-}
-
-static uint64_t ram_filesizeproc(void *file)
-{
- auto f = (iofile_ram *)file;
- return f->data->size();
-}
-
-
-static const io_procs iop_ram = {
- ram_closeproc,
- ram_seekproc,
- ram_readproc,
- ram_writeproc,
- ram_filesizeproc
-};
-
-static io_generic *ram_open(std::vector<u8> &data)
-{
- iofile_ram *f = new iofile_ram;
- f->data = &data;
- f->pos = 0;
- return new io_generic({ &iop_ram, f });
-}
-
-std::map<std::string, std::vector<floppy_image_format_t *>> formats_by_category;
-std::map<std::string, floppy_image_format_t *> formats_by_key;
-
-std::map<std::string, std::vector<fs_info>> fs_by_category;
-std::map<std::string, fs_info> fs_by_key;
-
-static std::vector<uint32_t> variants;
-
-struct enumerator;
-
-struct fs_enum : public filesystem_manager_t::floppy_enumerator {
- enumerator *m_en;
- fs_enum(enumerator *en) : filesystem_manager_t::floppy_enumerator(), m_en(en) {};
-
- void reg(const fs_info &fsi) const;
- virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) override;
- virtual void add_raw(const char *name, u32 key, const char *description) override;
-};
-
-struct enumerator : public mame_formats_enumerator {
- fs_enum fse;
-
- enumerator() : mame_formats_enumerator(), fse(this) {}
-
- virtual ~enumerator() = default;
- virtual void add(const cassette_image::Format *const *formats) {}
-
- std::vector<floppy_image_format_t *> *cf = nullptr;
- std::vector<fs_info> *cfs = nullptr;
- virtual void category(const char *name) {
- auto i = formats_by_category.find(name);
- if(i != formats_by_category.end()) {
- fprintf(stderr, "Collision on category name %s\n", name);
- exit(1);
- }
- cf = &formats_by_category[name];
- cfs = &fs_by_category[name];
- }
-
- virtual void add(floppy_format_type format) {
- auto f = format();
- std::string key = f->name();
- auto i = formats_by_key.find(key);
- if(i != formats_by_key.end()) {
- fprintf(stderr, "Collision on format key %s between \"%s\" and \"%s\".\n",
- key.c_str(),
- i->second->description(),
- f->description());
- exit(1);
- }
- cf->push_back(f);
- formats_by_key[key] = f;
- }
-
- virtual void add(filesystem_manager_type fs) {
- auto ff = fs();
- ff->enumerate_f(fse, floppy_image::FF_UNKNOWN, variants);
- }
-};
-
-void fs_enum::reg(const fs_info &fsi) const
-{
- std::string key = fsi.m_name;
- auto i = fs_by_key.find(key);
- if(i != fs_by_key.end()) {
- fprintf(stderr, "Collision on fs key %s between \"%s\" and \"%s\".\n",
- key.c_str(),
- i->second.m_description,
- fsi.m_description);
- exit(1);
- }
- m_en->cfs->push_back(fsi);
- fs_by_key.emplace(key, fsi);
-}
-
-void fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description)
-{
- fs_info fsi(manager, type, image_size, name, description);
- reg(fsi);
-}
-
-void fs_enum::add_raw(const char *name, u32 key, const char *description)
-{
- fs_info fsi(name, key, description);
- reg(fsi);
-}
-
-void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...)
-{
- va_list arg;
- va_start(arg, format);
- vprintf(format, arg);
- va_end(arg);
-}
-
-
-static void init_formats()
-{
- enumerator en;
- mame_formats_full_list(en);
-}
-
-static floppy_image_format_t *find_format_by_name(const char *name)
-{
- auto i = formats_by_key.find(name);
- if(i == formats_by_key.end())
- return nullptr;
- return i->second;
-}
-
-static floppy_image_format_t *find_format_by_identify(io_generic *image)
-{
- int best = 0;
- floppy_image_format_t *best_fif = nullptr;
-
- for(const auto &e : formats_by_key) {
- floppy_image_format_t *fif = e.second;
- int score = fif->identify(image, floppy_image::FF_UNKNOWN, variants);
- if(score > best) {
- best = score;
- best_fif = fif;
- }
- }
- return best_fif;
-}
-
-static const fs_info *find_fs_by_name(const char *name)
-{
- auto i = fs_by_key.find(name);
- if(i == fs_by_key.end())
- return nullptr;
- return &i->second;
-}
+static formats_table formats;
static void display_usage()
{
fprintf(stderr, "Usage: \n");
- fprintf(stderr, " floptool.exe identify <inputfile> [<inputfile> ...] -- Identify a floppy image format\n");
- fprintf(stderr, " floptool.exe convert [input_format|auto] output_format <inputfile> <outputfile> -- Convert a floppy image\n");
+ fprintf(stderr, " floptool.exe identify <inputfile> [<inputfile> ...] -- Identify an image format\n");
+ fprintf(stderr, " floptool.exe flopconvert [input_format|auto] output_format <inputfile> <outputfile> -- Convert a floppy image\n");
fprintf(stderr, " floptool.exe flopcreate output_format filesystem <outputfile> -- Create a preformatted floppy image\n");
fprintf(stderr, " floptool.exe flopdir input_format filesystem <image> -- List the contents of a floppy image\n");
fprintf(stderr, " floptool.exe flopread input_format filesystem <image> <path> <outputfile> -- Extract a file from a floppy image\n");
@@ -279,40 +32,56 @@ static void display_usage()
}
static void display_formats()
-{
+{
int sk = 0;
- for(const auto &e : formats_by_key) {
+ for(const auto &e : formats.floppy_format_info_by_key) {
+ int sz = e.first.size();
+ if(sz > sk)
+ sk = sz;
+ }
+
+ for(const auto &e : formats.filesystem_format_by_key) {
int sz = e.first.size();
if(sz > sk)
sk = sz;
}
- for(const auto &e : fs_by_key) {
+
+ for(const auto &e : formats.floppy_create_info_by_key) {
int sz = e.first.size();
if(sz > sk)
sk = sz;
}
fprintf(stderr, "Supported floppy formats:\n\n");
- for(const auto &e : formats_by_category)
+ for(const auto &e : formats.floppy_format_info_by_category)
if(!e.second.empty()) {
fprintf(stderr, "%s:\n", e.first.c_str());
- for(floppy_image_format_t *fif : e.second)
- fprintf(stderr, " %-*s - %s [%s]\n", sk, fif->name(), fif->description(), fif->extensions());
+ for(auto *fif : e.second)
+ fprintf(stderr, " %-*s r%c - %s [%s]\n", sk, fif->m_format->name(), fif->m_format->supports_save() ? 'w' : '-', fif->m_format->description(), fif->m_format->extensions());
}
fprintf(stderr, "\n\n");
- fprintf(stderr, "Supported floppy filesystems:\n\n");
- for(const auto &e : fs_by_category)
+ fprintf(stderr, "Supported filesystems (with floppy formatting names):\n\n");
+ for(const auto &e : formats.filesystem_format_by_category)
if(!e.second.empty()) {
fprintf(stderr, "%s:\n", e.first.c_str());
- for(const fs_info &fs : e.second)
- fprintf(stderr, " %-*s %c%c%c - %s\n",
+ for(const auto &f : e.second) {
+ fprintf(stderr, " %-*s %c%c%c %c%c%c - %s\n",
sk,
- fs.m_name,
- !fs.m_manager || fs.m_manager->can_format() ? 'f' : '-',
- fs.m_manager && fs.m_manager->can_read() ? 'r' : '-',
- fs.m_manager && fs.m_manager->can_write() ? 'w' : '-',
- fs.m_description);
+ f->m_manager->name(),
+ f->m_floppy || f->m_floppy_raw ? 'F' : '-',
+ f->m_hd ? 'H' : '-',
+ f->m_cd ? 'C' : '-',
+ f->m_manager->can_format() || f->m_floppy_raw ? 'f' : '-',
+ f->m_manager->can_read() ? 'r' : '-',
+ f->m_manager->can_write() ? 'w' : '-',
+ f->m_manager->description());
+ for(auto &f2 : f->m_floppy_create)
+ fprintf(stderr, " %-*s - %s\n",
+ sk,
+ f2->m_name,
+ f2->m_description);
+ }
}
}
@@ -323,177 +92,157 @@ static void display_full_usage()
display_usage();
fprintf(stderr, "\n");
display_formats();
- fprintf(stderr, "\nExample usage:\n");
- fprintf(stderr, " floptool.exe identify image.dsk\n\n");
}
static int identify(int argc, char *argv[])
{
- if (argc<3) {
+ // Need to detect CHDs too
+
+ if(argc<3) {
fprintf(stderr, "Missing name of file to identify.\n\n");
display_usage();
return 1;
}
+ int sz = 0;
for(int i=2; i<argc; i++) {
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[i]);
- FILE *f = fopen(argv[i], "rb");
- if (!f) {
- perror(msg);
- return 1;
+ int len = strlen(argv[i]);
+ if(len > sz)
+ sz = len;
+ }
+
+ for(int i=2; i<argc; i++) {
+ image_handler ih;
+ ih.set_on_disk_path(argv[i]);
+ auto scores = ih.identify(formats);
+ if(scores.empty())
+ printf("%-*s : Unknown format\n", sz, argv[i]);
+ int sz2 = 0;
+ for(const auto &e : scores) {
+ int len = strlen(e.second->m_format->name());
+ if(len > sz2)
+ sz2 = len;
+ }
+
+ bool first = true;
+ for(const auto &e : scores) {
+ printf("%-*s %c %3d - %-*s %s\n", sz, first ? argv[i] : "", first ? ':' : ' ', e.first, sz2, e.second->m_format->name(), e.second->m_format->description());
+ first = false;
}
- io_generic io;
- io.file = f;
- io.procs = &stdio_ioprocs_noclose;
- io.filler = 0xff;
-
- floppy_image_format_t *best_fif = find_format_by_identify(&io);
- if (best_fif)
- printf("%s : %s\n", argv[i], best_fif->description());
- else
- printf("%s : Unknown format\n", argv[i]);
- fclose(f);
}
return 0;
}
-static int convert(int argc, char *argv[])
+static const floppy_format_info *find_floppy_source_format(const char *name, image_handler &ih)
{
- if (argc!=6) {
- fprintf(stderr, "Incorrect number of arguments.\n\n");
- display_usage();
- return 1;
- }
-
- floppy_image_format_t *source_format, *dest_format;
-
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
- return 1;
- }
- io_generic source_io;
- source_io.file = f;
- source_io.procs = &stdio_ioprocs_noclose;
- source_io.filler = 0xff;
-
- if(!core_stricmp(argv[2], "auto")) {
- source_format = find_format_by_identify(&source_io);
- if(!source_format) {
- fprintf(stderr, "Error: Could not identify the format of file %s\n", argv[4]);
- return 1;
+ const floppy_format_info *source_format;
+ if(!core_stricmp(name, "auto")) {
+ auto scores = ih.identify(formats);
+ if(scores.empty()) {
+ fprintf(stderr, "Error: Could not identify the format of file %s\n", ih.get_on_disk_path().c_str());
+ return nullptr;
+ }
+ if(scores.size() >= 2 && scores[0].first == scores[1].first) {
+ fprintf(stderr, "Ambiguous source format. Possible formats:\n");
+ int sz = 0;
+ for(const auto &e : scores) {
+ int len = strlen(e.second->m_format->name());
+ if(len > sz)
+ sz = len;
+ }
+
+ for(const auto &e : scores)
+ printf(" %3d - %-*s %s\n", e.first, sz, e.second->m_format->name(), e.second->m_format->description());
+ return nullptr;
}
+ source_format = scores[0].second;
} else {
- source_format = find_format_by_name(argv[2]);
+ source_format = formats.find_floppy_format_info_by_key(name);
if(!source_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
- return 1;
+ fprintf(stderr, "Error: Format '%s' unknown\n", name);
+ return nullptr;
+
}
}
+ return source_format;
+}
- dest_format = find_format_by_name(argv[3]);
- if(!dest_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]);
+static int flopconvert(int argc, char *argv[])
+{
+ if(argc!=6) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage();
return 1;
}
- if(!dest_format->supports_save()) {
- fprintf(stderr, "Error: saving to format '%s' unsupported\n", argv[3]);
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- sprintf(msg, "Error opening %s for writing", argv[5]);
- f = fopen(argv[5], "wb");
- if (!f) {
- perror(msg);
+ const floppy_format_info *dest_format = formats.find_floppy_format_info_by_key(argv[3]);
+ if(!dest_format) {
+ fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]);
return 1;
}
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
-
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
- if(!source_format->load(&source_io, floppy_image::FF_UNKNOWN, variants, &image)) {
- fprintf(stderr, "Error: parsing input file as '%s' failed\n", source_format->name());
+ if(!dest_format->m_format->supports_save()) {
+ fprintf(stderr, "Error: Aaving to format '%s' unsupported\n", argv[3]);
return 1;
}
- if(!dest_format->save(&dest_io, variants, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", dest_format->name());
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
return 1;
}
- fclose((FILE *)source_io.file);
- fclose((FILE *)dest_io.file);
+ ih.set_on_disk_path(argv[5]);
+
+ if(ih.floppy_save(dest_format)) {
+ fprintf(stderr, "Error: Saving as format '%s' failed\n", dest_format->m_format->name());
+ return 1;
+ }
return 0;
}
-static int create(int argc, char *argv[])
+static int flopcreate(int argc, char *argv[])
{
- if (argc!=5) {
+ if(argc!=5) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto dest_format = find_format_by_name(argv[2]);
+ auto dest_format = formats.find_floppy_format_info_by_key(argv[2]);
if(!dest_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
+ fprintf(stderr, "Error: Floppy format '%s' unknown\n", argv[3]);
return 1;
}
-
- auto source_fs = find_fs_by_name(argv[3]);
- if(!source_fs) {
- fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
+ if(!dest_format->m_format->supports_save()) {
+ fprintf(stderr, "Error: Saving to format '%s' unsupported\n", argv[3]);
return 1;
}
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
-
- if(source_fs->m_type) {
- fs_meta_data meta;
-
- std::vector<u8> img(source_fs->m_image_size);
- fsblk_vec_t blockdev(img);
- auto fs = source_fs->m_manager->mount(blockdev);
- fs->format(meta);
-
- auto iog = ram_open(img);
- auto source_format = source_fs->m_type();
- source_format->load(iog, floppy_image::FF_UNKNOWN, variants, &image);
- delete source_format;
- delete iog;
-
- } else
- fs_unformatted::format(source_fs->m_key, &image);
-
- char msg[4096];
- sprintf(msg, "Error opening %s for writing", argv[4]);
- auto f = fopen(argv[4], "wb");
- if (!f) {
- perror(msg);
+ auto create_fs = formats.find_floppy_create_info_by_key(argv[3]);
+ if(!create_fs) {
+ fprintf(stderr, "Error: Floppy creation format '%s' unknown\n", argv[3]);
return 1;
}
-
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
-
- if(!dest_format->save(&dest_io, variants, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", dest_format->name());
+ if(!create_fs->m_manager->can_format()) {
+ fprintf(stderr, "Error: Floppy creation format '%s' does not support creating new images\n", argv[3]);
return 1;
}
- fclose((FILE *)dest_io.file);
+ fs_meta_data meta;
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
- return 0;
+ ih.floppy_create(create_fs, meta);
+ return ih.floppy_save(dest_format);
}
static void dir_scan(u32 depth, filesystem_t::dir_t dir, std::vector<std::vector<std::string>> &entries, const std::unordered_map<fs_meta_name, size_t> &nmap, size_t nc, const std::vector<fs_meta_description> &dmetad, const std::vector<fs_meta_description> &fmetad)
@@ -541,14 +290,14 @@ static void dir_scan(u32 depth, filesystem_t::dir_t dir, std::vector<std::vector
}
}
-static int generic_dir(const filesystem_manager_t *fm, fsblk_t &blockdev)
+static int generic_dir(image_handler &ih)
{
- auto load_fs = fm->mount(blockdev);
- auto vmetad = fm->volume_meta_description();
- auto fmetad = fm->file_meta_description();
- auto dmetad = fm->directory_meta_description();
+ auto [fsm, fs] = ih.get_fs();
+ auto vmetad = fsm->volume_meta_description();
+ auto fmetad = fsm->file_meta_description();
+ auto dmetad = fsm->directory_meta_description();
- auto vmeta = load_fs->metadata();
+ auto vmeta = fs->metadata();
if(!vmeta.empty()) {
std::string vinf = "Volume:";
for(const auto &e : vmetad)
@@ -568,8 +317,8 @@ static int generic_dir(const filesystem_manager_t *fm, fsblk_t &blockdev)
std::unordered_map<fs_meta_name, size_t> nmap;
for(size_t i = 0; i != names.size(); i++)
nmap[names[i]] = i;
-
- auto root = load_fs->root();
+
+ auto root = fs->root();
std::vector<std::vector<std::string>> entries;
entries.resize(1);
@@ -599,69 +348,55 @@ static int generic_dir(const filesystem_manager_t *fm, fsblk_t &blockdev)
static int flopdir(int argc, char *argv[])
{
- if (argc!=5) {
+ if(argc!=5) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto format = find_format_by_name(argv[2]);
- if(!format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- auto fs = find_fs_by_name(argv[3]);
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
return 1;
}
if(!fs->m_manager || !fs->m_manager->can_read()) {
- fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
return 1;
}
- io_generic io;
- io.file = f;
- io.procs = &stdio_ioprocs_noclose;
- io.filler = 0xff;
-
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
- if(!format->load(&io, floppy_image::FF_UNKNOWN, variants, &image)) {
- fprintf(stderr, "Error: parsing input file as '%s' failed\n", format->name());
+
+ if(ih.floppy_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- std::vector<u8> img;
- auto iog = ram_open(img);
- auto load_format = fs->m_type();
- load_format->save(iog, variants, &image);
- delete load_format;
- delete iog;
-
- fsblk_vec_t blockdev(img);
- return generic_dir(fs->m_manager, blockdev);
+ return generic_dir(ih);
}
-// Should use chd&friends instead, but one thing at a time
-
static int hddir(int argc, char *argv[])
{
- if (argc!=4) {
+ if(argc!=4) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto fs = find_fs_by_name(argv[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
@@ -672,114 +407,22 @@ static int hddir(int argc, char *argv[])
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[3]);
- FILE *f = fopen(argv[3], "rb");
- if (!f) {
- perror(msg);
+ if(ih.hd_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- rewind(f);
- std::vector<u8> img(size);
- fread(img.data(), size, 1, f);
- fclose(f);
-
- fsblk_vec_t blockdev(img);
- return generic_dir(fs->m_manager, blockdev);
-}
-
-static std::vector<std::string> path_split(const filesystem_manager_t *fm, std::string path)
-{
- std::string opath = path;
- std::vector<std::string> rpath;
- if(fm->has_subdirectories()) {
- std::string element;
- char sep = fm->directory_separator();
- for(char c : opath) {
- if(c == sep) {
- if(!element.empty()) {
- rpath.push_back(element);
- element.clear();
- }
- } else
- element += c;
- }
- if(!element.empty())
- rpath.push_back(element);
-
- } else
- rpath.push_back(opath);
-
- return rpath;
-}
-
-static std::vector<u8> fload(std::string path)
-{
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", path.c_str());
- auto fi = fopen(path.c_str(), "rb");
- if (!fi) {
- perror(msg);
- exit(1);
- }
- fseek(fi, 0, SEEK_END);
- long size = ftell(fi);
- std::vector<u8> filedata(size);
- fseek(fi, 0, SEEK_SET);
- fread(filedata.data(), filedata.size(), 1, fi);
- fclose(fi);
-
- return filedata;
-}
-
-static void fsave(std::string path, const std::vector<u8> &data)
-{
- char msg[4096];
- sprintf(msg, "Error opening %s for writing", path.c_str());
- auto fo = fopen(path.c_str(), "wb");
- if (!fo) {
- perror(msg);
- exit(1);
- }
-
- fwrite(data.data(), data.size(), 1, fo);
- fclose(fo);
-}
-
-static bool fexists(std::string path)
-{
- auto f = fopen(path.c_str(), "rb");
- if(f != nullptr) {
- fclose(f);
- return true;
- }
- return false;
-}
-
-
-static std::string path_make_rsrc(std::string path)
-{
- auto p = path.end();
- while(p != path.begin() && p[-1] != '/')
- p--;
- std::string rpath(path.begin(), p);
- rpath += "._";
- rpath += std::string(p, path.end());
- return rpath;
+ return generic_dir(ih);
}
-
-static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const char *srcpath, const char *dstpath)
+static int generic_read(image_handler &ih, const char *srcpath, const char *dstpath)
{
- auto load_fs = fm->mount(blockdev);
+ auto [fsm, fs] = ih.get_fs();
- std::vector<std::string> path = path_split(fm, srcpath);
+ std::vector<std::string> path = ih.path_split(srcpath);
- auto dir = load_fs->root();
+ auto dir = fs->root();
std::string apath;
for(unsigned int i = 0; i < path.size() - 1; i++) {
auto c = dir.contents();
@@ -788,15 +431,15 @@ static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const
if(c[j].m_name == path[i])
break;
if(j == c.size()) {
- fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
if(c[j].m_type != fs_dir_entry_type::dir) {
- fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
dir = dir.dir_get(c[j].m_key);
- apath += fm->directory_separator() + path[i];
+ apath += fsm->directory_separator() + path[i];
}
auto c = dir.contents();
@@ -805,38 +448,23 @@ static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const
if(c[j].m_name == path.back())
break;
if(j == c.size()) {
- fprintf(stderr, "Error: file %s%c%s not found\n", apath.c_str(), fm->directory_separator(), path.back().c_str());
+ fprintf(stderr, "Error: file %s%c%s not found\n", apath.c_str(), fsm->directory_separator(), path.back().c_str());
return 1;
}
auto file = dir.file_get(c[j].m_key);
auto meta = file.metadata();
if(!meta.has(fs_meta_name::length)) {
- fprintf(stderr, "Error: %s%c%s is not a readable file\n", apath.c_str(), fm->directory_separator(), path.back().c_str());
+ fprintf(stderr, "Error: %s%c%s is not a readable file\n", apath.c_str(), fsm->directory_separator(), path.back().c_str());
return 1;
}
- fsave(dstpath, file.read_all());
-
- bool has_rsrc = fm->has_rsrc() && meta.has(fs_meta_name::rsrc_length);
-
- if(has_rsrc) {
- std::string rpath = path_make_rsrc(dstpath);
-
- auto filedata = file.rsrc_read_all();
- filedata.insert(filedata.begin(), 0x2a, 0);
+ image_handler::fsave(dstpath, file.read_all());
- u8 *head = filedata.data();
- filesystem_t::w32b(head+0x00, 0x00051607); // Magic
- filesystem_t::w32b(head+0x04, 0x00020000); // Version
- filesystem_t::fill(head+0x08, 0, 16); // Filler
- filesystem_t::w16b(head+0x18, 1); // Number of entries
- filesystem_t::w32b(head+0x1a, 2); // Resource fork
- filesystem_t::w32b(head+0x22, 0x2a); // Offset in the file
- filesystem_t::w32b(head+0x26, filedata.size()); // Length
+ bool has_rsrc = fsm->has_rsrc() && meta.has(fs_meta_name::rsrc_length);
- fsave(rpath, filedata);
- }
+ if(has_rsrc)
+ image_handler::fsave_rsrc(image_handler::path_make_rsrc(dstpath), file.rsrc_read_all());
return 0;
}
@@ -844,70 +472,55 @@ static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const
static int flopread(int argc, char *argv[])
{
- if (argc!=7) {
+ if(argc!=7) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto format = find_format_by_name(argv[2]);
- if(!format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- auto fs = find_fs_by_name(argv[3]);
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
return 1;
}
if(!fs->m_manager || !fs->m_manager->can_read()) {
- fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
return 1;
}
- io_generic io;
- io.file = f;
- io.procs = &stdio_ioprocs_noclose;
- io.filler = 0xff;
-
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
- if(!format->load(&io, floppy_image::FF_UNKNOWN, variants, &image)) {
- fprintf(stderr, "Error: parsing input file as '%s' failed\n", format->name());
+
+ if(ih.floppy_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- std::vector<u8> img;
- auto iog = ram_open(img);
- auto load_format = fs->m_type();
- load_format->save(iog, variants, &image);
- delete load_format;
- delete iog;
-
- fsblk_vec_t blockdev(img);
- return generic_read(fs->m_manager, blockdev, argv[5], argv[6]);
+ return generic_read(ih, argv[5], argv[6]);
}
-
-// Should use chd&friends instead, but one thing at a time
-
static int hdread(int argc, char *argv[])
{
- if (argc!=6) {
+ if(argc!=6) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto fs = find_fs_by_name(argv[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
@@ -918,33 +531,23 @@ static int hdread(int argc, char *argv[])
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[3]);
- FILE *f = fopen(argv[3], "rb");
- if (!f) {
- perror(msg);
+ if(ih.hd_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- rewind(f);
- std::vector<u8> img(size);
- fread(img.data(), size, 1, f);
- fclose(f);
-
- fsblk_vec_t blockdev(img);
- return generic_read(fs->m_manager, blockdev, argv[4], argv[5]);
+
+ return generic_read(ih, argv[4], argv[5]);
}
-static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, const char *srcpath, const char *dstpath)
+static int generic_write(image_handler &ih, const char *srcpath, const char *dstpath)
{
- auto load_fs = fm->mount(blockdev);
+ auto [fsm, fs] = ih.get_fs();
- std::vector<std::string> path = path_split(fm, dstpath);
+ std::vector<std::string> path = ih.path_split(dstpath);
- auto dir = load_fs->root();
+ auto dir = fs->root();
std::string apath;
for(unsigned int i = 0; i < path.size() - 1; i++) {
auto c = dir.contents();
@@ -953,15 +556,15 @@ static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, cons
if(c[j].m_name == path[i])
break;
if(j == c.size()) {
- fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
if(c[j].m_type != fs_dir_entry_type::dir) {
- fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
dir = dir.dir_get(c[j].m_key);
- apath += fm->directory_separator() + path[i];
+ apath += fsm->directory_separator() + path[i];
}
@@ -969,33 +572,18 @@ static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, cons
meta.set(fs_meta_name::name, path.back());
auto file = dir.file_create(meta);
- auto filedata = fload(srcpath);
+ auto filedata = image_handler::fload(srcpath);
file.replace(filedata);
- bool has_rsrc = fm->has_rsrc();
+ bool has_rsrc = fsm->has_rsrc();
if(has_rsrc) {
- std::string rpath = path_make_rsrc(dstpath);
-
- if(fexists(rpath)) {
- filedata = fload(rpath);
- const u8 *head = filedata.data();
-
- if(filesystem_t::r32b(head+0x00) == 0x00051607 &&
- filesystem_t::r32b(head+0x04) == 0x00020000) {
- u16 nent = filesystem_t::r16b(head+0x18);
- for(u16 i=0; i != nent; i++) {
- const u8 *e = head + 12*i;
- if(filesystem_t::r32b(e+0) == 2) {
- u32 start = filesystem_t::r32b(e+4);
- u32 len = filesystem_t::r32b(e+8);
- filedata.erase(filedata.begin(), filedata.begin() + start);
- filedata.erase(filedata.begin() + len, filedata.end());
- file.rsrc_replace(filedata);
- break;
- }
- }
- }
+ std::string rpath = image_handler::path_make_rsrc(dstpath);
+
+ if(image_handler::fexists(rpath)) {
+ filedata = image_handler::fload_rsrc(rpath);
+ if(!filedata.empty())
+ file.rsrc_replace(filedata);
}
}
@@ -1005,92 +593,64 @@ static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, cons
static int flopwrite(int argc, char *argv[])
{
- if (argc!=7) {
+ if(argc!=7) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto format = find_format_by_name(argv[2]);
- if(!format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- auto fs = find_fs_by_name(argv[3]);
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
return 1;
}
if(!fs->m_manager || !fs->m_manager->can_read()) {
- fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
return 1;
}
- io_generic io;
- io.file = f;
- io.procs = &stdio_ioprocs_noclose;
- io.filler = 0xff;
-
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
- if(!format->load(&io, floppy_image::FF_UNKNOWN, variants, &image)) {
- fprintf(stderr, "Error: parsing input file as '%s' failed\n", format->name());
- return 1;
- }
-
- std::vector<u8> img;
- auto iog = ram_open(img);
- auto load_format = fs->m_type();
- load_format->save(iog, variants, &image);
- fsblk_vec_t blockdev(img);
- generic_write(fs->m_manager, blockdev, argv[5], argv[6]);
-
- load_format->load(iog, image.get_form_factor(), variants, &image);
- delete load_format;
- delete iog;
-
- sprintf(msg, "Error oapening %s for writing", argv[4]);
- f = fopen(argv[4], "wb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
+
+ int err = generic_write(ih, argv[5], argv[6]);
+ if(err)
+ return err;
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
-
- if(!format->save(&dest_io, variants, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", format->name());
+ ih.fs_to_floppy();
+ if(ih.floppy_save(source_format))
return 1;
- }
-
- fclose((FILE *)dest_io.file);
+
return 0;
}
-
-// Should use chd&friends instead, but one thing at a time
-
static int hdwrite(int argc, char *argv[])
{
- if (argc!=6) {
+ if(argc!=6) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto fs = find_fs_by_name(argv[2]);
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
@@ -1101,52 +661,41 @@ static int hdwrite(int argc, char *argv[])
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[3]);
- FILE *f = fopen(argv[3], "rb");
- if (!f) {
- perror(msg);
+ if(ih.hd_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- rewind(f);
- std::vector<u8> img(size);
- fread(img.data(), size, 1, f);
- fclose(f);
-
- fsblk_vec_t blockdev(img);
- return generic_write(fs->m_manager, blockdev, argv[4], argv[5]);
-}
+ return generic_write(ih, argv[4], argv[5]);
+}
int CLIB_DECL main(int argc, char *argv[])
{
- init_formats();
+ formats.init();
- if (argc == 1) {
+ if(argc == 1) {
display_full_usage();
return 0;
}
try {
- if (!core_stricmp("identify", argv[1]))
+ if(!core_stricmp("identify", argv[1]))
return identify(argc, argv);
- else if (!core_stricmp("convert", argv[1]))
- return convert(argc, argv);
- else if (!core_stricmp("flopcreate", argv[1]))
- return create(argc, argv);
- else if (!core_stricmp("flopdir", argv[1]))
+ else if(!core_stricmp("flopconvert", argv[1]))
+ return flopconvert(argc, argv);
+ else if(!core_stricmp("flopcreate", argv[1]))
+ return flopcreate(argc, argv);
+ else if(!core_stricmp("flopdir", argv[1]))
return flopdir(argc, argv);
- else if (!core_stricmp("flopread", argv[1]))
+ else if(!core_stricmp("flopread", argv[1]))
return flopread(argc, argv);
- else if (!core_stricmp("flopwrite", argv[1]))
+ else if(!core_stricmp("flopwrite", argv[1]))
return flopwrite(argc, argv);
- else if (!core_stricmp("hddir", argv[1]))
+ else if(!core_stricmp("hddir", argv[1]))
return hddir(argc, argv);
- else if (!core_stricmp("hdread", argv[1]))
+ else if(!core_stricmp("hdread", argv[1]))
return hdread(argc, argv);
- else if (!core_stricmp("hdwrite", argv[1]))
+ else if(!core_stricmp("hdwrite", argv[1]))
return hdwrite(argc, argv);
else {
fprintf(stderr, "Unknown command '%s'\n\n", argv[1]);
diff --git a/src/tools/image_handler.cpp b/src/tools/image_handler.cpp
new file mode 100644
index 00000000000..a1bec2d34ef
--- /dev/null
+++ b/src/tools/image_handler.cpp
@@ -0,0 +1,481 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Image generic handler class and helpers
+
+#include "image_handler.h"
+#include "formats/all.h"
+#include "formats/fsblk_vec.h"
+#include "formats/fs_unformatted.h"
+
+// Fatalerror implementation
+
+emu_fatalerror::emu_fatalerror(util::format_argument_pack<std::ostream> const &args)
+ : emu_fatalerror(0, args)
+{
+}
+
+emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack<std::ostream> const &args)
+ : m_text(util::string_format(args))
+ , m_code(_exitcode)
+{
+}
+
+// io_generic from vector<u8>
+
+static void ram_closeproc(void *file)
+{
+ auto f = (iofile_ram *)file;
+ delete f;
+}
+
+static int ram_seekproc(void *file, int64_t offset, int whence)
+{
+ auto f = (iofile_ram *)file;
+ switch(whence) {
+ case SEEK_SET: f->pos = offset; break;
+ case SEEK_CUR: f->pos += offset; break;
+ case SEEK_END: f->pos = f->data->size() + offset; break;
+ }
+
+ if(whence == SEEK_CUR)
+ f->pos = std::max<int64_t>(f->pos, 0);
+ else
+ f->pos = std::clamp<int64_t>(f->pos, 0, f->data->size());
+ return 0;
+}
+
+static size_t ram_readproc(void *file, void *buffer, size_t length)
+{
+ auto f = (iofile_ram *)file;
+ size_t l = std::min<std::common_type_t<size_t, int64_t> >(length, f->data->size() - f->pos);
+ memcpy(buffer, f->data->data() + f->pos, l);
+ return l;
+}
+
+static size_t ram_writeproc(void *file, const void *buffer, size_t length)
+{
+ auto f = (iofile_ram *)file;
+ size_t l = std::max<std::common_type_t<size_t, int64_t> >(f->pos + length, f->data->size());
+ f->data->resize(l);
+ memcpy(f->data->data() + f->pos, buffer, length);
+ return length;
+}
+
+static uint64_t ram_filesizeproc(void *file)
+{
+ auto f = (iofile_ram *)file;
+ return f->data->size();
+}
+
+
+static const io_procs iop_ram = {
+ ram_closeproc,
+ ram_seekproc,
+ ram_readproc,
+ ram_writeproc,
+ ram_filesizeproc
+};
+
+io_generic *ram_open(std::vector<u8> &data)
+{
+ iofile_ram *f = new iofile_ram;
+ f->data = &data;
+ f->pos = 0;
+ return new io_generic({ &iop_ram, f });
+}
+
+
+// Format enumeration
+
+namespace {
+ struct enumerator : public mame_formats_enumerator {
+ formats_table *m_table;
+ std::string m_category;
+
+ enumerator(formats_table *table) : mame_formats_enumerator(), m_table(table), m_category("None") {}
+
+ virtual ~enumerator() = default;
+ virtual void add(const cassette_image::Format *const *formats) {}
+
+ virtual void category(const char *name) {
+ m_category = name;
+ }
+
+ virtual void add(floppy_format_type format) {
+ m_table->floppy_format_infos.emplace_back(std::make_unique<floppy_format_info>(format(), m_category));
+ }
+
+ virtual void add(const filesystem_manager_t &fs) {
+ m_table->filesystem_formats.emplace_back(std::make_unique<filesystem_format>(&fs, m_category));
+ }
+ };
+
+ struct fs_enum : public filesystem_manager_t::floppy_enumerator {
+ filesystem_format *m_format;
+
+ fs_enum(filesystem_format *format) : m_format(format) {}
+
+ virtual void add(floppy_format_type type, u32 image_size, const char *name, const char *description) override {
+ m_format->m_floppy = true;
+ m_format->m_floppy_create.emplace_back(std::make_unique<floppy_create_info>(m_format->m_manager, type, image_size, name, description));
+ }
+
+ virtual void add_raw(const char *name, u32 key, const char *description) override {
+ m_format->m_floppy_raw = true;
+ m_format->m_floppy_create.emplace_back(std::make_unique<floppy_create_info>(name, key, description));
+ }
+ };
+}
+
+void formats_table::init()
+{
+ std::vector<uint32_t> variants;
+
+ enumerator en(this);
+ mame_formats_full_list(en);
+
+ for(auto &f : filesystem_formats) {
+ fs_enum fen(f.get());
+ f->m_manager->enumerate_f(fen, floppy_image::FF_UNKNOWN, variants);
+ }
+
+ for(auto &f : floppy_format_infos) {
+ auto *ff = f.get();
+ std::string key = ff->m_format->name();
+ auto i = floppy_format_info_by_key.find(key);
+ if(i != floppy_format_info_by_key.end()) {
+ fprintf(stderr, "Collision on floppy format name %s between \"%s\" and \"%s\".\n",
+ ff->m_format->name(),
+ ff->m_format->description(),
+ i->second->m_format->description());
+ exit(1);
+ }
+
+ floppy_format_info_by_key[key] = ff;
+ floppy_format_info_by_category[ff->m_category].push_back(ff);
+ }
+
+ for(auto &f : filesystem_formats) {
+ auto *ff = f.get();
+ std::string key = ff->m_manager->name();
+ auto i = filesystem_format_by_key.find(key);
+ if(i != filesystem_format_by_key.end()) {
+ fprintf(stderr, "Collision on filesystem name %s between \"%s\" and \"%s\".\n",
+ ff->m_manager->name(),
+ ff->m_manager->description(),
+ i->second->m_manager->description());
+ exit(1);
+ }
+
+ filesystem_format_by_key[key] = ff;
+ filesystem_format_by_category[ff->m_category].push_back(ff);
+
+ for(auto &f2 : ff->m_floppy_create) {
+ auto *ff2 = f2.get();
+ key = ff2->m_name;
+ auto i = floppy_create_info_by_key.find(key);
+ if(i != floppy_create_info_by_key.end()) {
+ fprintf(stderr, "Collision on floppy create name %s between \"%s\" and \"%s\".\n",
+ ff2->m_name,
+ ff2->m_description,
+ i->second->m_description);
+ exit(1);
+ }
+
+ floppy_create_info_by_key[key] = ff2;
+ }
+ }
+}
+
+const floppy_format_info *formats_table::find_floppy_format_info_by_key(const std::string &key) const
+{
+ auto i = floppy_format_info_by_key.find(key);
+ return i == floppy_format_info_by_key.end() ? nullptr : i->second;
+}
+
+const filesystem_format *formats_table::find_filesystem_format_by_key(const std::string &key) const
+{
+ auto i = filesystem_format_by_key.find(key);
+ return i == filesystem_format_by_key.end() ? nullptr : i->second;
+}
+
+const floppy_create_info *formats_table::find_floppy_create_info_by_key(const std::string &key) const
+{
+ auto i = floppy_create_info_by_key.find(key);
+ return i == floppy_create_info_by_key.end() ? nullptr : i->second;
+}
+
+
+// Image handling
+
+std::vector<u8> image_handler::fload(std::string path)
+{
+ char msg[4096];
+ sprintf(msg, "Error opening %s for reading", path.c_str());
+ auto fi = fopen(path.c_str(), "rb");
+ if(!fi) {
+ perror(msg);
+ exit(1);
+ }
+ fseek(fi, 0, SEEK_END);
+ long size = ftell(fi);
+ std::vector<u8> filedata(size);
+ fseek(fi, 0, SEEK_SET);
+ fread(filedata.data(), filedata.size(), 1, fi);
+ fclose(fi);
+
+ return filedata;
+}
+
+std::vector<u8> image_handler::fload_rsrc(std::string path)
+{
+ auto filedata = fload(path);
+ const u8 *head = filedata.data();
+
+ if(filesystem_t::r32b(head+0x00) == 0x00051607 &&
+ filesystem_t::r32b(head+0x04) == 0x00020000) {
+ u16 nent = filesystem_t::r16b(head+0x18);
+ for(u16 i=0; i != nent; i++) {
+ const u8 *e = head + 12*i;
+ if(filesystem_t::r32b(e+0) == 2) {
+ u32 start = filesystem_t::r32b(e+4);
+ u32 len = filesystem_t::r32b(e+8);
+ filedata.erase(filedata.begin(), filedata.begin() + start);
+ filedata.erase(filedata.begin() + len, filedata.end());
+ return filedata;
+ }
+ }
+ }
+ filedata.clear();
+ return filedata;
+}
+
+void image_handler::fsave(std::string path, const std::vector<u8> &data)
+{
+ char msg[4096];
+ sprintf(msg, "Error opening %s for writing", path.c_str());
+ auto fo = fopen(path.c_str(), "wb");
+ if(!fo) {
+ perror(msg);
+ exit(1);
+ }
+
+ fwrite(data.data(), data.size(), 1, fo);
+ fclose(fo);
+}
+
+void image_handler::fsave_rsrc(std::string path, const std::vector<u8> &data)
+{
+ u8 head[0x2a];
+
+ filesystem_t::w32b(head+0x00, 0x00051607); // Magic
+ filesystem_t::w32b(head+0x04, 0x00020000); // Version
+ filesystem_t::fill(head+0x08, 0, 16); // Filler
+ filesystem_t::w16b(head+0x18, 1); // Number of entries
+ filesystem_t::w32b(head+0x1a, 2); // Resource fork
+ filesystem_t::w32b(head+0x22, 0x2a); // Offset in the file
+ filesystem_t::w32b(head+0x26, data.size()); // Length
+
+ char msg[4096];
+ sprintf(msg, "Error opening %s for writing", path.c_str());
+ auto fo = fopen(path.c_str(), "wb");
+ if(!fo) {
+ perror(msg);
+ exit(1);
+ }
+
+ fwrite(head, sizeof(head), 1, fo);
+ fwrite(data.data(), data.size(), 1, fo);
+ fclose(fo);
+}
+
+image_handler::image_handler() : m_floppy_image(84, 2, floppy_image::FF_UNKNOWN)
+{
+}
+
+void image_handler::set_on_disk_path(std::string path)
+{
+ m_on_disk_path = path;
+}
+
+std::vector<std::pair<u8, const floppy_format_info *>> image_handler::identify(const formats_table &formats)
+{
+ std::vector<std::pair<u8, const floppy_format_info *>> res;
+ std::vector<uint32_t> variants;
+
+ std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path);
+ FILE *f = fopen(m_on_disk_path.c_str(), "rb");
+ if (!f) {
+ perror(msg.c_str());
+ return res;
+ }
+
+ io_generic io;
+ io.file = f;
+ io.procs = &stdio_ioprocs_noclose;
+ io.filler = 0xff;
+
+ for(const auto &e : formats.floppy_format_info_by_key) {
+ u8 score = e.second->m_format->identify(&io, floppy_image::FF_UNKNOWN, variants);
+ if(score)
+ res.emplace_back(std::make_pair(score, e.second));
+ }
+
+ fclose(f);
+
+ return res;
+}
+
+bool image_handler::floppy_load(const floppy_format_info *format)
+{
+ std::vector<uint32_t> variants;
+ std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path);
+ FILE *f = fopen(m_on_disk_path.c_str(), "rb");
+ if (!f) {
+ perror(msg.c_str());
+ return true;
+ }
+
+ io_generic io;
+ io.file = f;
+ io.procs = &stdio_ioprocs_noclose;
+ io.filler = 0xff;
+
+ return !format->m_format->load(&io, floppy_image::FF_UNKNOWN, variants, &m_floppy_image);
+}
+
+bool image_handler::floppy_save(const floppy_format_info *format)
+{
+ std::vector<uint32_t> variants;
+ std::string msg = util::string_format("Error opening %s for writing", m_on_disk_path);
+ FILE *f = fopen(m_on_disk_path.c_str(), "wb");
+ if (!f) {
+ perror(msg.c_str());
+ return true;
+ }
+
+ io_generic io;
+ io.file = f;
+ io.procs = &stdio_ioprocs_noclose;
+ io.filler = 0xff;
+
+ return !format->m_format->save(&io, variants, &m_floppy_image);
+}
+
+void image_handler::floppy_create(const floppy_create_info *format, fs_meta_data meta)
+{
+ if(format->m_type) {
+ std::vector<uint32_t> variants;
+ std::vector<u8> img(format->m_image_size);
+ fsblk_vec_t blockdev(img);
+ auto fs = format->m_manager->mount(blockdev);
+ fs->format(meta);
+
+ auto iog = ram_open(img);
+ auto source_format = format->m_type();
+ source_format->load(iog, floppy_image::FF_UNKNOWN, variants, &m_floppy_image);
+ delete source_format;
+ delete iog;
+
+ } else
+ fs_unformatted::format(format->m_key, &m_floppy_image);
+}
+
+bool image_handler::floppy_mount_fs(const filesystem_format *format)
+{
+ m_floppy_fs_converter = nullptr;
+ for(const auto &ci : format->m_floppy_create) {
+ if(ci->m_type != m_floppy_fs_converter) {
+ std::vector<uint32_t> variants;
+ m_floppy_fs_converter = ci->m_type;
+ m_sector_image.clear();
+ auto iog = ram_open(m_sector_image);
+ auto load_format = m_floppy_fs_converter();
+ load_format->save(iog, variants, &m_floppy_image);
+ delete load_format;
+ delete iog;
+ }
+
+ if(ci->m_image_size == m_sector_image.size())
+ goto success;
+ }
+ m_floppy_fs_converter = nullptr;
+ m_sector_image.clear();
+ return true;
+
+ success:
+ m_fsblk.reset(new fsblk_vec_t(m_sector_image));
+ m_fsm = format->m_manager;
+ m_fs = m_fsm->mount(*m_fsblk);
+ return false;
+}
+
+bool image_handler::hd_mount_fs(const filesystem_format *format)
+{
+ // Should use the chd mechanisms, one thing at a time...
+
+ m_sector_image = fload(m_on_disk_path);
+ m_fsblk.reset(new fsblk_vec_t(m_sector_image));
+ m_fsm = format->m_manager;
+ m_fs = m_fsm->mount(*m_fsblk);
+ return false;
+}
+
+void image_handler::fs_to_floppy()
+{
+ std::vector<uint32_t> variants;
+ auto iog = ram_open(m_sector_image);
+ auto format = m_floppy_fs_converter();
+ format->load(iog, floppy_image::FF_UNKNOWN, variants, &m_floppy_image);
+ delete format;
+ delete iog;
+}
+
+std::vector<std::string> image_handler::path_split(std::string path) const
+{
+ std::string opath = path;
+ std::vector<std::string> rpath;
+ if(m_fsm->has_subdirectories()) {
+ std::string element;
+ char sep = m_fsm->directory_separator();
+ for(char c : opath) {
+ if(c == sep) {
+ if(!element.empty()) {
+ rpath.push_back(element);
+ element.clear();
+ }
+ } else
+ element += c;
+ }
+ if(!element.empty())
+ rpath.push_back(element);
+
+ } else
+ rpath.push_back(opath);
+
+ return rpath;
+}
+
+bool image_handler::fexists(std::string path)
+{
+ auto f = fopen(path.c_str(), "rb");
+ if(f != nullptr) {
+ fclose(f);
+ return true;
+ }
+ return false;
+}
+
+
+std::string image_handler::path_make_rsrc(std::string path)
+{
+ auto p = path.end();
+ while(p != path.begin() && p[-1] != '/')
+ p--;
+ std::string rpath(path.begin(), p);
+ rpath += "._";
+ rpath += std::string(p, path.end());
+ return rpath;
+}
+
diff --git a/src/tools/image_handler.h b/src/tools/image_handler.h
new file mode 100644
index 00000000000..bef852aaed6
--- /dev/null
+++ b/src/tools/image_handler.h
@@ -0,0 +1,121 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Image generic handler class and helpers
+
+#ifndef TOOLS_IMAGE_HANDLER_H
+#define TOOLS_IMAGE_HANDLER_H
+
+#include "../emu/emucore.h"
+#include "formats/fsmgr.h"
+
+#include <map>
+#include <vector>
+#include <memory>
+
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+
+struct iofile_ram {
+ std::vector<u8> *data;
+ int64_t pos;
+};
+
+io_generic *ram_open(std::vector<u8> &data);
+
+struct floppy_format_info {
+ floppy_image_format_t *m_format;
+ std::string m_category;
+
+ floppy_format_info(floppy_image_format_t *format, std::string category) : m_format(format), m_category(category) {}
+};
+
+struct floppy_create_info {
+ const filesystem_manager_t *m_manager;
+
+ floppy_format_type m_type;
+ u32 m_image_size;
+ u32 m_key;
+ const char *m_name;
+ const char *m_description;
+
+ floppy_create_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) :
+ m_manager(manager), m_type(type), m_image_size(image_size), m_key(0), m_name(name), m_description(description)
+ { }
+
+ floppy_create_info(const char *name, u32 key, const char *description) :
+ m_manager(nullptr), m_type(nullptr), m_image_size(0), m_key(key), m_name(name), m_description(description)
+ { }
+};
+
+struct filesystem_format {
+ const filesystem_manager_t *m_manager;
+ std::vector<std::unique_ptr<floppy_create_info>> m_floppy_create;
+ std::string m_category;
+ bool m_floppy, m_floppy_raw, m_hd, m_cd;
+
+ filesystem_format(const filesystem_manager_t *manager, std::string category) : m_manager(manager), m_category(category), m_floppy(false), m_floppy_raw(false), m_hd(false), m_cd(false) {}
+};
+
+struct formats_table {
+ std::vector<std::unique_ptr<floppy_format_info>> floppy_format_infos;
+ std::vector<std::unique_ptr<filesystem_format>> filesystem_formats;
+
+ std::map<std::string, const floppy_format_info *> floppy_format_info_by_key;
+ std::map<std::string, const filesystem_format *> filesystem_format_by_key;
+ std::map<std::string, const floppy_create_info *> floppy_create_info_by_key;
+
+ std::map<std::string, std::vector<const floppy_format_info *>> floppy_format_info_by_category;
+ std::map<std::string, std::vector<const filesystem_format *>> filesystem_format_by_category;
+
+ void init();
+
+ const floppy_format_info *find_floppy_format_info_by_key(const std::string &key) const;
+ const filesystem_format *find_filesystem_format_by_key(const std::string &key) const;
+ const floppy_create_info *find_floppy_create_info_by_key(const std::string &key) const;
+};
+
+class image_handler {
+public:
+ image_handler();
+
+ void set_on_disk_path(std::string path);
+ const std::string &get_on_disk_path() const { return m_on_disk_path; }
+
+ std::vector<std::pair<u8, const floppy_format_info *>> identify(const formats_table &formats);
+
+ bool floppy_load(const floppy_format_info *format);
+ bool floppy_save(const floppy_format_info *format);
+
+ void floppy_create(const floppy_create_info *format, fs_meta_data meta);
+ bool floppy_mount_fs(const filesystem_format *format);
+ bool hd_mount_fs(const filesystem_format *format);
+ void fs_to_floppy();
+
+ std::pair<const filesystem_manager_t *, filesystem_t *> get_fs() const { return std::make_pair(m_fsm, m_fs.get()); }
+
+ std::vector<std::string> path_split(std::string path) const;
+
+ static std::vector<u8> fload(std::string path);
+ static std::vector<u8> fload_rsrc(std::string path);
+ static void fsave(std::string path, const std::vector<u8> &data);
+ static void fsave_rsrc(std::string path, const std::vector<u8> &data);
+ static bool fexists(std::string path);
+ static std::string path_make_rsrc(std::string path);
+
+private:
+ std::string m_on_disk_path;
+
+ floppy_image m_floppy_image;
+
+ floppy_format_type m_floppy_fs_converter;
+ std::vector<u8> m_sector_image;
+ std::unique_ptr<fsblk_t> m_fsblk;
+ const filesystem_manager_t *m_fsm;
+ std::unique_ptr<filesystem_t> m_fs;
+
+};
+
+#endif
+