mirror of
https://github.com/holub/mame
synced 2025-07-05 18:08:04 +03:00
floppy: Change the internal format to flux changes, update the mfi format accordingly (keep read compatibility with the old mfi)
This commit is contained in:
parent
40033c809a
commit
08f28cee11
@ -1127,11 +1127,6 @@ uint32_t floppy_image_device::find_position(attotime &base, const attotime &when
|
||||
return res;
|
||||
}
|
||||
|
||||
bool floppy_image_device::test_track_last_entry_warps(const std::vector<uint32_t> &buf) const
|
||||
{
|
||||
return !((buf[buf.size() - 1]^buf[0]) & floppy_image::MG_MASK);
|
||||
}
|
||||
|
||||
attotime floppy_image_device::position_to_time(const attotime &base, int position) const
|
||||
{
|
||||
return base + attotime::from_double(position/angular_speed);
|
||||
@ -1141,19 +1136,13 @@ void floppy_image_device::cache_fill_index(const std::vector<uint32_t> &buf, int
|
||||
{
|
||||
int cells = buf.size();
|
||||
|
||||
if(index != 0 || !test_track_last_entry_warps(buf)) {
|
||||
cache_index = index;
|
||||
cache_start_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK);
|
||||
} else {
|
||||
cache_index = cells - 1;
|
||||
cache_start_time = position_to_time(base - rev_time, buf[cache_index] & floppy_image::TIME_MASK);
|
||||
}
|
||||
|
||||
cache_index = index;
|
||||
cache_start_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK);
|
||||
cache_entry = buf[cache_index];
|
||||
|
||||
index ++;
|
||||
if(index >= cells) {
|
||||
index = test_track_last_entry_warps(buf) ? 1 : 0;
|
||||
index = 0;
|
||||
base += rev_time;
|
||||
}
|
||||
|
||||
@ -1268,161 +1257,146 @@ void floppy_image_device::write_flux(const attotime &start, const attotime &end,
|
||||
track_dirty = true;
|
||||
cache_clear();
|
||||
|
||||
attotime base;
|
||||
int start_pos = find_position(base, start);
|
||||
int end_pos = find_position(base, end);
|
||||
std::vector<wspan> wspans(1);
|
||||
|
||||
attotime base;
|
||||
wspans[0].start = find_position(base, start);
|
||||
wspans[0].end = find_position(base, end);
|
||||
|
||||
std::vector<int> trans_pos(transition_count);
|
||||
for(int i=0; i != transition_count; i++)
|
||||
trans_pos[i] = find_position(base, transitions[i]);
|
||||
wspans[0].flux_change_positions.push_back(find_position(base, transitions[i]));
|
||||
|
||||
wspan_split_on_wrap(wspans);
|
||||
|
||||
std::vector<uint32_t> &buf = image->get_buffer(cyl, ss, subcyl);
|
||||
|
||||
int index;
|
||||
if(!buf.empty())
|
||||
index = find_index(start_pos, buf);
|
||||
else {
|
||||
index = 0;
|
||||
if(buf.empty()) {
|
||||
buf.push_back(floppy_image::MG_N);
|
||||
buf.push_back(floppy_image::MG_E | 199999999);
|
||||
}
|
||||
|
||||
uint32_t cur_mg;
|
||||
if((buf[index] & floppy_image::TIME_MASK) == start_pos) {
|
||||
if(index)
|
||||
cur_mg = buf[index-1];
|
||||
else
|
||||
cur_mg = buf[buf.size() - 1];
|
||||
} else
|
||||
cur_mg = buf[index];
|
||||
wspan_remove_damaged(wspans, buf);
|
||||
wspan_write(wspans, buf);
|
||||
|
||||
cur_mg &= floppy_image::MG_MASK;
|
||||
if(cur_mg == floppy_image::MG_N || cur_mg == floppy_image::MG_D)
|
||||
cur_mg = floppy_image::MG_A;
|
||||
|
||||
uint32_t pos = start_pos;
|
||||
int ti = 0;
|
||||
int cells = buf.size();
|
||||
if(transition_count != 0 && trans_pos[0] == pos) {
|
||||
cur_mg = cur_mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
ti ++;
|
||||
}
|
||||
while(pos != end_pos) {
|
||||
if(buf.size() < cells+10)
|
||||
buf.resize(cells+200);
|
||||
uint32_t next_pos;
|
||||
if(ti != transition_count)
|
||||
next_pos = trans_pos[ti++];
|
||||
else
|
||||
next_pos = end_pos;
|
||||
if(next_pos > pos)
|
||||
write_zone(&buf[0], cells, index, pos, next_pos, cur_mg);
|
||||
else {
|
||||
write_zone(&buf[0], cells, index, pos, 200000000, cur_mg);
|
||||
index = 0;
|
||||
write_zone(&buf[0], cells, index, 0, next_pos, cur_mg);
|
||||
}
|
||||
pos = next_pos;
|
||||
cur_mg = cur_mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
}
|
||||
|
||||
buf.resize(cells);
|
||||
cache_clear();
|
||||
}
|
||||
|
||||
void floppy_image_device::write_zone(uint32_t *buf, int &cells, int &index, uint32_t spos, uint32_t epos, uint32_t mg)
|
||||
void floppy_image_device::wspan_split_on_wrap(std::vector<wspan> &wspans)
|
||||
{
|
||||
cache_clear();
|
||||
while(spos < epos) {
|
||||
while(index != cells-1 && (buf[index+1] & floppy_image::TIME_MASK) <= spos)
|
||||
index++;
|
||||
int ne = wspans.size();
|
||||
for(int i=0; i != ne; i++)
|
||||
if(wspans[i].end < wspans[i].start) {
|
||||
wspans.resize(wspans.size()+1);
|
||||
auto &ws = wspans[i];
|
||||
auto &we = wspans.back();
|
||||
we.start = 0;
|
||||
we.end = ws.end;
|
||||
ws.end = 200000000;
|
||||
int start = ws.start;
|
||||
int split_index;
|
||||
for(split_index = 0; split_index != ws.flux_change_positions.size(); split_index++)
|
||||
if(ws.flux_change_positions[split_index] < start)
|
||||
break;
|
||||
if(split_index == 0)
|
||||
std::swap(ws.flux_change_positions, we.flux_change_positions);
|
||||
|
||||
uint32_t ref_start = buf[index] & floppy_image::TIME_MASK;
|
||||
uint32_t ref_end = index == cells-1 ? 200000000 : buf[index+1] & floppy_image::TIME_MASK;
|
||||
uint32_t ref_mg = buf[index] & floppy_image::MG_MASK;
|
||||
else {
|
||||
we.flux_change_positions.resize(ws.flux_change_positions.size() - split_index);
|
||||
std::copy(ws.flux_change_positions.begin() + split_index, ws.flux_change_positions.end(), we.flux_change_positions.begin());
|
||||
ws.flux_change_positions.erase(ws.flux_change_positions.begin() + split_index, ws.flux_change_positions.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can't overwrite a damaged zone
|
||||
if(ref_mg == floppy_image::MG_D) {
|
||||
spos = ref_end;
|
||||
continue;
|
||||
void floppy_image_device::wspan_remove_damaged(std::vector<wspan> &wspans, const std::vector<uint32_t> &track)
|
||||
{
|
||||
for(size_t pos = 0; pos != track.size(); pos++)
|
||||
if((track[pos] & floppy_image::MG_MASK) == floppy_image::MG_D) {
|
||||
int start = track[pos] & floppy_image::TIME_MASK;
|
||||
int end = track[pos+1] & floppy_image::TIME_MASK;
|
||||
int ne = wspans.size();
|
||||
for(int i=0; i != ne; i++) {
|
||||
// D range outside of span range
|
||||
if(wspans[i].start > end || wspans[i].end <= start)
|
||||
continue;
|
||||
|
||||
// D range covers span range
|
||||
if(wspans[i].start >= start && wspans[i].end-1 <= end) {
|
||||
wspans.erase(wspans.begin() + i);
|
||||
i --;
|
||||
ne --;
|
||||
continue;
|
||||
}
|
||||
|
||||
// D range covers the start of the span range
|
||||
if(wspans[i].start >= start && wspans[i].end-1 > end) {
|
||||
wspans[i].start = end+1;
|
||||
while(!wspans[i].flux_change_positions.empty() && wspans[i].flux_change_positions[0] <= end)
|
||||
wspans[i].flux_change_positions.erase(wspans[i].flux_change_positions.begin());
|
||||
continue;
|
||||
}
|
||||
|
||||
// D range covers the end of the span range
|
||||
if(wspans[i].start < start && wspans[i].end-1 <= end) {
|
||||
wspans[i].end = start;
|
||||
while(!wspans[i].flux_change_positions.empty() && wspans[i].flux_change_positions[wspans[i].flux_change_positions.size()-1] >= start)
|
||||
wspans[i].flux_change_positions.erase(wspans[i].flux_change_positions.end()-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// D range is inside the span range, need to split
|
||||
int id = wspans.size();
|
||||
wspans.resize(id+1);
|
||||
wspans[id].start = end+1;
|
||||
wspans[id].end = wspans[i].end;
|
||||
wspans[id].flux_change_positions = wspans[i].flux_change_positions;
|
||||
wspans[i].end = start;
|
||||
while(!wspans[i].flux_change_positions.empty() && wspans[i].flux_change_positions[wspans[i].flux_change_positions.size()-1] >= start)
|
||||
wspans[i].flux_change_positions.erase(wspans[i].flux_change_positions.end()-1);
|
||||
while(!wspans[id].flux_change_positions.empty() && wspans[id].flux_change_positions[0] <= end)
|
||||
wspans[id].flux_change_positions.erase(wspans[id].flux_change_positions.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void floppy_image_device::wspan_write(const std::vector<wspan> &wspans, std::vector<uint32_t> &track)
|
||||
{
|
||||
for(const auto &ws : wspans) {
|
||||
unsigned si, ei;
|
||||
for(si = 0; si != track.size(); si++)
|
||||
if((track[si] & floppy_image::TIME_MASK) >= ws.start)
|
||||
break;
|
||||
for(ei = si; ei != track.size(); ei++)
|
||||
if((track[ei] & floppy_image::TIME_MASK) >= ws.end)
|
||||
break;
|
||||
|
||||
// Reduce neutral zone at the start, if there's one
|
||||
if(si != track.size() && (track[si] & floppy_image::MG_MASK) == floppy_image::MG_E) {
|
||||
// Neutral zone is over the whole range, split it and adapt si/ei
|
||||
if(si == ei) {
|
||||
track.insert(track.begin() + si, floppy_image::MG_E | (ws.start-1));
|
||||
track.insert(track.begin() + si + 1, (track[si-1] & floppy_image::MG_MASK) | ws.end);
|
||||
si = ei = si+1;
|
||||
} else {
|
||||
// Reduce the zone size
|
||||
track[si] = floppy_image::MG_E | (ws.start-1);
|
||||
si ++;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a neutral zone at the end and reduce it if needed
|
||||
if(ei != track.size() && (track[ei] & floppy_image::MG_MASK) == floppy_image::MG_E) {
|
||||
track[ei-1] = floppy_image::MG_N | ws.end;
|
||||
ei --;
|
||||
}
|
||||
|
||||
// If the zone is of the type we want, we don't need to touch it
|
||||
if(ref_mg == mg) {
|
||||
spos = ref_end;
|
||||
continue;
|
||||
}
|
||||
// Clear the covered zone
|
||||
track.erase(track.begin() + si, track.begin() + ei);
|
||||
|
||||
// Check the overlaps, act accordingly
|
||||
if(spos == ref_start) {
|
||||
if(epos >= ref_end) {
|
||||
// Full overlap, that cell is dead, we need to see which ones we can extend
|
||||
uint32_t prev_mg = index != 0 ? buf[index-1] & floppy_image::MG_MASK : ~0;
|
||||
uint32_t next_mg = index != cells-1 ? buf[index+1] & floppy_image::MG_MASK : ~0;
|
||||
if(prev_mg == mg) {
|
||||
if(next_mg == mg) {
|
||||
// Both match, merge all three in one
|
||||
memmove(buf+index, buf+index+2, (cells-index-2)*sizeof(uint32_t));
|
||||
cells -= 2;
|
||||
index--;
|
||||
|
||||
} else {
|
||||
// Previous matches, drop the current cell
|
||||
memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(uint32_t));
|
||||
cells --;
|
||||
}
|
||||
|
||||
} else {
|
||||
if(next_mg == mg) {
|
||||
// Following matches, extend it
|
||||
memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(uint32_t));
|
||||
cells --;
|
||||
buf[index] = mg | spos;
|
||||
} else {
|
||||
// None match, convert the current cell
|
||||
buf[index] = mg | spos;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
spos = ref_end;
|
||||
|
||||
} else {
|
||||
// Overlap at the start only
|
||||
// Check if we can just extend the previous cell
|
||||
if(index != 0 && (buf[index-1] & floppy_image::MG_MASK) == mg)
|
||||
buf[index] = ref_mg | epos;
|
||||
else {
|
||||
// Otherwise we need to insert a new cell
|
||||
if(index != cells-1)
|
||||
memmove(buf+index+1, buf+index, (cells-index)*sizeof(uint32_t));
|
||||
cells++;
|
||||
buf[index] = mg | spos;
|
||||
buf[index+1] = ref_mg | epos;
|
||||
}
|
||||
spos = epos;
|
||||
}
|
||||
|
||||
} else {
|
||||
if(epos >= ref_end) {
|
||||
// Overlap at the end only
|
||||
// If we can't just extend the following cell, we need to insert a new one
|
||||
if(index == cells-1 || (buf[index+1] & floppy_image::MG_MASK) != mg) {
|
||||
if(index != cells-1)
|
||||
memmove(buf+index+2, buf+index+1, (cells-index-1)*sizeof(uint32_t));
|
||||
cells++;
|
||||
}
|
||||
buf[index+1] = mg | spos;
|
||||
index++;
|
||||
spos = ref_end;
|
||||
|
||||
} else {
|
||||
// Full inclusion
|
||||
// We need to split the zone in 3
|
||||
if(index != cells-1)
|
||||
memmove(buf+index+3, buf+index+1, (cells-index-1)*sizeof(uint32_t));
|
||||
cells += 2;
|
||||
buf[index+1] = mg | spos;
|
||||
buf[index+2] = ref_mg | epos;
|
||||
spos = epos;
|
||||
}
|
||||
// Insert the flux changes
|
||||
for(auto f : ws.flux_change_positions) {
|
||||
track.insert(track.begin() + si, floppy_image::MG_F | f);
|
||||
si ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,6 @@ protected:
|
||||
attotime revolution_start_time, rev_time;
|
||||
uint32_t revolution_count;
|
||||
int cyl, subcyl;
|
||||
|
||||
/* Current floppy zone cache */
|
||||
attotime cache_start_time, cache_end_time, cache_weak_start;
|
||||
attotime amplifier_freakout_time;
|
||||
@ -246,15 +245,24 @@ protected:
|
||||
wpt_cb cur_wpt_cb;
|
||||
led_cb cur_led_cb;
|
||||
|
||||
|
||||
// Temporary structure storing a write span
|
||||
struct wspan {
|
||||
int start, end;
|
||||
std::vector<int> flux_change_positions;
|
||||
};
|
||||
|
||||
static void wspan_split_on_wrap(std::vector<wspan> &wspans);
|
||||
static void wspan_remove_damaged(std::vector<wspan> &wspans, const std::vector<uint32_t> &track);
|
||||
static void wspan_write(const std::vector<wspan> &wspans, std::vector<uint32_t> &track);
|
||||
|
||||
void register_formats();
|
||||
|
||||
void check_led();
|
||||
uint32_t find_position(attotime &base, const attotime &when);
|
||||
int find_index(uint32_t position, const std::vector<uint32_t> &buf) const;
|
||||
bool test_track_last_entry_warps(const std::vector<uint32_t> &buf) const;
|
||||
attotime position_to_time(const attotime &base, int position) const;
|
||||
|
||||
void write_zone(uint32_t *buf, int &cells, int &index, uint32_t spos, uint32_t epos, uint32_t mg);
|
||||
void commit_image();
|
||||
|
||||
u32 hash32(u32 val) const;
|
||||
|
@ -1674,7 +1674,21 @@ bool a2_woz_format::load(util::random_read &io, uint32_t form_factor, const std:
|
||||
if (r32(img, trks_off + 4) == 0)
|
||||
return false;
|
||||
|
||||
generate_track_from_bitstream(track, head, &img[boff], r32(img, trks_off + 4), image, subtrack, 0xffff);
|
||||
uint32_t track_size = r32(img, trks_off + 4);
|
||||
|
||||
// With 5.25 floppies the end-of-track may be missing
|
||||
// if unformatted. Accept track length down to 95% of
|
||||
// 51090, otherwise pad it
|
||||
|
||||
bool short_track = !is_35 && track_size < 48535;
|
||||
|
||||
if(short_track) {
|
||||
std::vector<uint8_t> buffer(6387, 0);
|
||||
memcpy(buffer.data(), &img[boff], (track_size + 7) / 8);
|
||||
generate_track_from_bitstream(track, head, buffer.data(), 51090, image, subtrack, 0xffff);
|
||||
|
||||
} else
|
||||
generate_track_from_bitstream(track, head, &img[boff], track_size, image, subtrack, 0xffff);
|
||||
|
||||
if(is_35 && !track && head)
|
||||
image->set_variant(r32(img, trks_off + 4) >= 90000 ? floppy_image::DSHD : floppy_image::DSDD);
|
||||
|
@ -177,9 +177,7 @@ bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
|
||||
#endif
|
||||
index_count = 0;
|
||||
//index_polarity = 0;
|
||||
uint32_t mg = floppy_image::MG_A;
|
||||
int tpos = 0;
|
||||
buf[tpos++] = mg;
|
||||
for(int i=0; i<tsize; i++) {
|
||||
uint8_t v = data[i];
|
||||
if((v & 0x7f) == 0x7f) // 0x7F : no transition, but a carry (FF is a board-on-fire error and is checked for above)
|
||||
@ -202,23 +200,19 @@ bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
|
||||
//if (trans_time <= MIN_THRESH) osd_printf_verbose("dfi_dsk: Throwing out short transition of length %d\n", trans_time);
|
||||
// the normal case: write the transition at the appropriate time
|
||||
if ((prev_time == 0) || ((trans_time > MIN_THRESH) && (trans_time <= MAX_THRESH))) {
|
||||
mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
buf[tpos++] = mg | uint32_t((200000000ULL*cur_time)/index_time);
|
||||
buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*cur_time)/index_time);
|
||||
prev_time = cur_time;
|
||||
}
|
||||
// the long case: we probably missed a transition, stuff an extra guessed one in there to see if it helps
|
||||
if (trans_time > MAX_THRESH) {
|
||||
mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
if (((track%2)==0)&&(head==0)) osd_printf_info("dfi_dsk: missed transition, total time for transition is %d\n",trans_time);
|
||||
#ifndef FAKETRANS_ONE
|
||||
buf[tpos++] = mg | uint32_t((200000000ULL*(cur_time-(trans_time/2)))/index_time); // generate imaginary transition at half period
|
||||
buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*(cur_time-(trans_time/2)))/index_time); // generate imaginary transition at half period
|
||||
#else
|
||||
buf[tpos++] = mg | uint32_t((200000000ULL*(cur_time-((trans_time*2)/3)))/index_time);
|
||||
mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
buf[tpos++] = mg | uint32_t((200000000ULL*(cur_time-(trans_time/3)))/index_time);
|
||||
buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*(cur_time-((trans_time*2)/3)))/index_time);
|
||||
buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*(cur_time-(trans_time/3)))/index_time);
|
||||
#endif
|
||||
mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
buf[tpos++] = mg | uint32_t(200000000ULL*cur_time/index_time); // generate transition now
|
||||
buf[tpos++] = floppy_image::MG_F | uint32_t(200000000ULL*cur_time/index_time); // generate transition now
|
||||
prev_time = cur_time;
|
||||
}
|
||||
}
|
||||
|
@ -91,9 +91,10 @@ bool floppy_image::track_is_formatted(int track, int head, int subtrack)
|
||||
const auto &data = track_array[idx][head].cell_data;
|
||||
if(data.empty())
|
||||
return false;
|
||||
if(data.size() == 1 && (data[0] & MG_MASK) == MG_N)
|
||||
return false;
|
||||
return true;
|
||||
for(uint32_t mg : data)
|
||||
if((mg & floppy_image::MG_MASK) == floppy_image::MG_F)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *floppy_image::get_variant_name(uint32_t form_factor, uint32_t variant)
|
||||
@ -840,17 +841,11 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
|
||||
generate_track_from_levels(track, head, buffer, 0, image);
|
||||
}
|
||||
|
||||
void floppy_image_format_t::normalize_times(std::vector<uint32_t> &buffer)
|
||||
void floppy_image_format_t::normalize_times(std::vector<uint32_t> &buffer, uint32_t last_position)
|
||||
{
|
||||
unsigned int total_sum = 0;
|
||||
for(unsigned int i=0; i != buffer.size(); i++)
|
||||
total_sum += buffer[i] & floppy_image::TIME_MASK;
|
||||
|
||||
unsigned int current_sum = 0;
|
||||
for(unsigned int i=0; i != buffer.size(); i++) {
|
||||
uint32_t time = buffer[i] & floppy_image::TIME_MASK;
|
||||
buffer[i] = (buffer[i] & floppy_image::MG_MASK) | (200000000ULL * current_sum / total_sum);
|
||||
current_sum += time;
|
||||
buffer[i] = (buffer[i] & floppy_image::MG_MASK) | (200000000ULL * time / last_position);
|
||||
}
|
||||
}
|
||||
|
||||
@ -859,36 +854,11 @@ void floppy_image_format_t::generate_track_from_bitstream(int track, int head, c
|
||||
std::vector<uint32_t> &dest = image->get_buffer(track, head, subtrack);
|
||||
dest.clear();
|
||||
|
||||
// If the bitstream has an odd number of inversions, one needs to be added.
|
||||
// Put in in the middle of the half window after the center inversion, where
|
||||
// any fdc ignores it.
|
||||
|
||||
int inversions = 0;
|
||||
for(int i=0; i != track_size; i++)
|
||||
if(trackbuf[i >> 3] & (0x80 >> (i & 7)))
|
||||
inversions++;
|
||||
bool need_flux = inversions & 1;
|
||||
dest.push_back(floppy_image::MG_F | (i*2+1));
|
||||
|
||||
uint32_t cbit = floppy_image::MG_A;
|
||||
uint32_t count = 0;
|
||||
for(int i=0; i != track_size; i++)
|
||||
if(trackbuf[i >> 3] & (0x80 >> (i & 7))) {
|
||||
dest.push_back(cbit | (count+2));
|
||||
cbit = cbit == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
if(need_flux) {
|
||||
need_flux = false;
|
||||
dest.push_back(cbit | 1);
|
||||
cbit = cbit == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
count = 1;
|
||||
} else
|
||||
count = 2;
|
||||
} else
|
||||
count += 4;
|
||||
|
||||
if(count)
|
||||
dest.push_back(cbit | count);
|
||||
|
||||
normalize_times(dest);
|
||||
normalize_times(dest, track_size*2);
|
||||
|
||||
if(splice >= 0 || splice < track_size) {
|
||||
int splpos = uint64_t(200000000) * splice / track_size;
|
||||
@ -902,81 +872,23 @@ void floppy_image_format_t::generate_track_from_levels(int track, int head, std:
|
||||
splice_pos = splice_pos % trackbuf.size();
|
||||
uint32_t splice_angular_pos = trackbuf[splice_pos] & floppy_image::TIME_MASK;
|
||||
|
||||
// Check if we need to invert a cell to get an even number of
|
||||
// transitions on the whole track
|
||||
//
|
||||
// Also check if all MG values are valid
|
||||
|
||||
int transition_count = 0;
|
||||
for(auto & elem : trackbuf) {
|
||||
switch(elem & floppy_image::MG_MASK) {
|
||||
case MG_1:
|
||||
transition_count++;
|
||||
break;
|
||||
|
||||
case MG_W:
|
||||
throw std::runtime_error(util::string_format("Weak bits not yet handled, track %d head %d", track, head));
|
||||
|
||||
case MG_0:
|
||||
case floppy_image::MG_N:
|
||||
case floppy_image::MG_D:
|
||||
break;
|
||||
|
||||
case floppy_image::MG_A:
|
||||
case floppy_image::MG_B:
|
||||
default:
|
||||
throw std::invalid_argument(util::string_format("Incorrect MG information in generate_track_from_levels, track %d head %d", track, head));
|
||||
}
|
||||
}
|
||||
|
||||
if(transition_count & 1) {
|
||||
int pos = splice_pos;
|
||||
while((trackbuf[pos] & floppy_image::MG_MASK) != MG_0 && (trackbuf[pos] & floppy_image::MG_MASK) != MG_1) {
|
||||
pos++;
|
||||
if(pos == int(trackbuf.size()))
|
||||
pos = 0;
|
||||
if(pos == splice_pos)
|
||||
goto meh;
|
||||
}
|
||||
if((trackbuf[pos] & floppy_image::MG_MASK) == MG_0)
|
||||
trackbuf[pos] = (trackbuf[pos] & floppy_image::TIME_MASK) | MG_1;
|
||||
else
|
||||
trackbuf[pos] = (trackbuf[pos] & floppy_image::TIME_MASK) | MG_0;
|
||||
|
||||
meh:
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
// Maximal number of cells which happens when the buffer is all MG_1/MG_N alternated, which would be 3/2
|
||||
std::vector<uint32_t> &dest = image->get_buffer(track, head);
|
||||
dest.clear();
|
||||
|
||||
uint32_t cbit = floppy_image::MG_A;
|
||||
uint32_t count = 0;
|
||||
uint32_t total_time = 0;
|
||||
for(auto & elem : trackbuf) {
|
||||
uint32_t bit = elem & floppy_image::MG_MASK;
|
||||
uint32_t time = elem & floppy_image::TIME_MASK;
|
||||
if(bit == MG_0) {
|
||||
count += time;
|
||||
continue;
|
||||
}
|
||||
if(bit == MG_1) {
|
||||
count += time >> 1;
|
||||
dest.push_back(cbit | count);
|
||||
cbit = cbit == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
count = time - (time >> 1);
|
||||
continue;
|
||||
}
|
||||
dest.push_back(cbit | count);
|
||||
dest.push_back(elem);
|
||||
count = 0;
|
||||
if(bit == MG_1)
|
||||
dest.push_back(floppy_image::MG_F | (total_time + (time >> 1)));
|
||||
|
||||
else if(bit != MG_0)
|
||||
dest.push_back(bit | total_time);
|
||||
|
||||
total_time += time;
|
||||
}
|
||||
|
||||
if(count)
|
||||
dest.push_back(cbit | count);
|
||||
|
||||
normalize_times(dest);
|
||||
normalize_times(dest, total_time);
|
||||
image->set_write_splice_position(track, head, splice_angular_pos);
|
||||
}
|
||||
|
||||
@ -1390,7 +1302,14 @@ std::vector<bool> floppy_image_format_t::generate_bitstream_from_track(int track
|
||||
{
|
||||
std::vector<bool> trackbuf;
|
||||
std::vector<uint32_t> &tbuf = image->get_buffer(track, head, subtrack);
|
||||
if(tbuf.size() <= 1) {
|
||||
bool track_has_info = false;
|
||||
for(uint32_t mg : tbuf)
|
||||
if((mg & floppy_image::MG_MASK) == floppy_image::MG_F) {
|
||||
track_has_info = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!track_has_info) {
|
||||
// Unformatted track
|
||||
int track_size = 200000000/cell_size;
|
||||
trackbuf.resize(track_size, false);
|
||||
@ -1414,8 +1333,14 @@ std::vector<bool> floppy_image_format_t::generate_bitstream_from_track(int track
|
||||
|
||||
uint32_t scanned = 0;
|
||||
while(scanned < 200000000) {
|
||||
// Note that all magnetic cell type changes are considered
|
||||
// edges. No randomness added for neutral/damaged cells
|
||||
// Note that only MG_F edges are taken into account, the rest is ignored.
|
||||
// The lack of MG_F has been tested for previously.
|
||||
while((tbuf[cur_entry] & floppy_image::MG_MASK) != floppy_image::MG_F) {
|
||||
cur_entry ++;
|
||||
if(cur_entry == tbuf.size())
|
||||
cur_entry = 0;
|
||||
}
|
||||
|
||||
int edge = tbuf[cur_entry] & floppy_image::TIME_MASK;
|
||||
if(edge < cur_pos)
|
||||
edge += 200000000;
|
||||
@ -1474,11 +1399,8 @@ std::vector<bool> floppy_image_format_t::generate_bitstream_from_track(int track
|
||||
|
||||
// Wrap around
|
||||
if(cur_entry == int(tbuf.size())-1 &&
|
||||
(tbuf[cur_entry] & floppy_image::TIME_MASK) < cur_pos) {
|
||||
// Wrap to index 0 or 1 depending on whether there is a transition exactly at the index hole
|
||||
cur_entry = (tbuf[int(tbuf.size())-1] & floppy_image::MG_MASK) != (tbuf[0] & floppy_image::MG_MASK) ?
|
||||
0 : 1;
|
||||
}
|
||||
(tbuf[cur_entry] & floppy_image::TIME_MASK) < cur_pos)
|
||||
cur_entry = 0;
|
||||
}
|
||||
return trackbuf;
|
||||
}
|
||||
|
@ -230,8 +230,9 @@ protected:
|
||||
*/
|
||||
static void generate_track_from_levels(int track, int head, std::vector<uint32_t> &trackbuf, int splice_pos, floppy_image *image);
|
||||
|
||||
//! Normalize the times in a cell buffer to sum up to 200000000
|
||||
static void normalize_times(std::vector<uint32_t> &buffer);
|
||||
//! Normalize the times in a cell buffer to bring the
|
||||
//! 0..last_position range up to 0..200000000
|
||||
static void normalize_times(std::vector<uint32_t> &buffer, uint32_t last_position);
|
||||
|
||||
// Some conversion tables for gcr
|
||||
static const uint8_t gcr5fw_tb[0x10], gcr5bw_tb[0x20];
|
||||
@ -450,19 +451,22 @@ private:
|
||||
//! Internal format is close but not identical to the mfi format.
|
||||
//!
|
||||
//!
|
||||
|
||||
//! Track data consists of a series of 32-bits lsb-first values
|
||||
//! representing magnetic cells. Bits 0-27 indicate the absolute
|
||||
//! position of the start of the cell (not the size), and bits
|
||||
//! 28-31 the type. Type can be:
|
||||
//! - 0, MG_A -> Magnetic orientation A
|
||||
//! - 1, MG_B -> Magnetic orientation B
|
||||
//! - 2, MG_N -> Non-magnetized zone (neutral)
|
||||
//! - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
|
||||
//! representing the magnetic state. Bits 0-27 indicate the absolute
|
||||
//! position of encoded event, and bits ! 28-31 the type. Type can be:
|
||||
//! - 0, MG_F -> Flux orientation change
|
||||
//! - 1, MG_N -> Start of a non-magnetized zone (neutral)
|
||||
//! - 2, MG_D -> Start of a damaged zone, reads as neutral but cannot be changed by writing
|
||||
//! - 3, MG_E -> End of one of the previous zones, *inclusive*
|
||||
//!
|
||||
//! The position is in angular units of 1/200,000,000th of a turn.
|
||||
//! The last cell implicit end position is of course 200,000,000.
|
||||
//! A N or D zone must not wrap at the 200,000,000 position, it has to
|
||||
//! be split in two (the first finishing at 199,999,999, the second
|
||||
//! starting at 0)
|
||||
//!
|
||||
//! Unformatted tracks are encoded as zero-size.
|
||||
//! Unformatted tracks are encoded as zero-size, and are strictly equivalent
|
||||
//! to (MG_N, 0), (MG_E, 199,999,999)
|
||||
//!
|
||||
//! The "track splice" information indicates where to start writing
|
||||
//! if you try to rewrite a physical disk with the data. Some
|
||||
@ -491,10 +495,10 @@ public:
|
||||
TIME_MASK = 0x0fffffff,
|
||||
MG_MASK = 0xf0000000,
|
||||
MG_SHIFT = 28, //!< Bitshift constant for magnetic orientation data
|
||||
MG_A = (0 << MG_SHIFT), //!< - 0, MG_A -> Magnetic orientation A
|
||||
MG_B = (1 << MG_SHIFT), //!< - 1, MG_B -> Magnetic orientation B
|
||||
MG_N = (2 << MG_SHIFT), //!< - 2, MG_N -> Non-magnetized zone (neutral)
|
||||
MG_D = (3 << MG_SHIFT) //!< - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
|
||||
MG_F = (0 << MG_SHIFT), //!< - 0, MG_F -> Flux orientation change
|
||||
MG_N = (1 << MG_SHIFT), //!< - 1, MG_N -> Non-magnetized zone (neutral)
|
||||
MG_D = (2 << MG_SHIFT), //!< - 2, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
|
||||
MG_E = (3 << MG_SHIFT) //!< - 3, MG_E -> End of zone
|
||||
};
|
||||
|
||||
|
||||
|
@ -316,17 +316,11 @@ void hfe_format::generate_track_from_hfe_bitstream(int cyl, int head, int sample
|
||||
// HFE does not define subtracks; set to 0
|
||||
|
||||
// MG_1 / MG_0 are (logical) levels that indicate transition / no change
|
||||
// MG_A / MG_B are physical flux directions
|
||||
//
|
||||
// Cell: | AAAABBBB | = MG_1 = | BBBBAAAA |
|
||||
// | AAAAAAAA | = MG_0 = | BBBBBBBB |
|
||||
// MG_F is the position of a flux transition
|
||||
|
||||
std::vector<uint32_t> &dest = image->get_buffer(cyl, head, 0);
|
||||
dest.clear();
|
||||
|
||||
// Start with MG_A
|
||||
uint32_t cbit = floppy_image::MG_A;
|
||||
|
||||
int offset = 0x100;
|
||||
|
||||
if (head==0)
|
||||
@ -338,10 +332,6 @@ void hfe_format::generate_track_from_hfe_bitstream(int cyl, int head, int sample
|
||||
uint8_t current = 0;
|
||||
int time = 0;
|
||||
|
||||
dest.push_back(cbit | time);
|
||||
|
||||
cbit = floppy_image::MG_B;
|
||||
|
||||
// Oversampled FM images (250 kbit/s) start with a 0, where a 1 is
|
||||
// expected for 125 kbit/s.
|
||||
// In order to make an oversampled image look like a normally sampled one,
|
||||
@ -384,13 +374,8 @@ void hfe_format::generate_track_from_hfe_bitstream(int cyl, int head, int sample
|
||||
{
|
||||
time += samplelength;
|
||||
if ((current & 1)!=0)
|
||||
{
|
||||
// Append another transition to the vector
|
||||
dest.push_back(cbit | time);
|
||||
|
||||
// Toggle the cell level
|
||||
cbit = (cbit == floppy_image::MG_A)? floppy_image::MG_B : floppy_image::MG_A;
|
||||
}
|
||||
dest.push_back(floppy_image::MG_F | time);
|
||||
|
||||
// HFE uses little-endian bit order
|
||||
current >>= 1;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <zlib.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
|
||||
/*
|
||||
@ -31,31 +32,27 @@
|
||||
simple "compress" function.
|
||||
|
||||
Track data consists of a series of 32-bits lsb-first values
|
||||
representing magnetic cells. Bits 0-27 indicate the sizes, and bits
|
||||
28-31 the types. Type can be:
|
||||
- 0, MG_A -> Magnetic orientation A
|
||||
- 1, MG_B -> Magnetic orientation B
|
||||
- 2, MG_N -> Non-magnetized zone (neutral)
|
||||
- 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
|
||||
representing magnetic cells. Bits 0-27 indicate the position,
|
||||
delta-packed (e.g. difference with the previous position, starts at
|
||||
0), and bits 28-31 the types. Type can be:
|
||||
|
||||
Remember that the fdcs detect transitions, not absolute levels, so
|
||||
the actual physical significance of the orientation A and B is
|
||||
arbitrary.
|
||||
- 0, MG_F -> Flux orientation change
|
||||
- 1, MG_N -> Non-magnetized zone (neutral)
|
||||
- 2, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
|
||||
- 3, MG_E -> End of zone
|
||||
|
||||
Tracks data is aligned so that the index pulse is at the start,
|
||||
whether the disk is hard-sectored or not.
|
||||
|
||||
The size is the angular size in units of 1/200,000,000th of a turn.
|
||||
Such a size, not coincidentally at all, is also the flyover time in
|
||||
nanoseconds for a perfectly stable 300rpm drive. That makes the
|
||||
standard cell size of a MFM 3.5" DD floppy at 2000 exactly for
|
||||
instance (2us). Smallest expected cell size is 500 (ED density
|
||||
drives).
|
||||
The position is the angular position in units of 1/200,000,000th of
|
||||
a turn. A size in such units, not coincidentally at all, is also
|
||||
the flyover time in nanoseconds for a perfectly stable 300rpm drive.
|
||||
That makes the standard cell size of a MFM 3.5" DD floppy at 2000
|
||||
exactly for instance (2us). Smallest expected cell size is 500 (ED
|
||||
density drives).
|
||||
|
||||
The sum of all sizes must of course be 200,000,000.
|
||||
|
||||
An unformatted track is equivalent to one big MG_N cell covering a
|
||||
whole turn, but is encoded as zero-size.
|
||||
An unformatted track is equivalent to a pair (MG_N, 0), (MG_E,
|
||||
199999999) but is encoded as zero-size.
|
||||
|
||||
The "track splice" information indicates where to start writing
|
||||
if you try to rewrite a physical disk with the data. Some
|
||||
@ -72,7 +69,8 @@
|
||||
TODO: big-endian support
|
||||
*/
|
||||
|
||||
const char mfi_format::sign[16] = "MESSFLOPPYIMAGE"; // Includes the final \0
|
||||
const char mfi_format::sign_old[16] = "MESSFLOPPYIMAGE"; // Includes the final \0
|
||||
const char mfi_format::sign[16] = "MAMEFLOPPYIMAGE"; // Includes the final \0
|
||||
|
||||
mfi_format::mfi_format() : floppy_image_format_t()
|
||||
{
|
||||
@ -85,7 +83,7 @@ const char *mfi_format::name() const
|
||||
|
||||
const char *mfi_format::description() const
|
||||
{
|
||||
return "MESS floppy image";
|
||||
return "MAME floppy image";
|
||||
}
|
||||
|
||||
const char *mfi_format::extensions() const
|
||||
@ -104,7 +102,7 @@ int mfi_format::identify(util::random_read &io, uint32_t form_factor, const std:
|
||||
|
||||
size_t actual;
|
||||
io.read_at(0, &h, sizeof(header), actual);
|
||||
if(memcmp( h.sign, sign, 16 ) == 0 &&
|
||||
if((memcmp( h.sign, sign, 16) == 0 || memcmp( h.sign, sign_old, 16) == 0) &&
|
||||
(h.cyl_count & CYLINDER_MASK) <= 84 &&
|
||||
(h.cyl_count >> RESOLUTION_SHIFT) < 3 &&
|
||||
h.head_count <= 2 &&
|
||||
@ -129,7 +127,46 @@ bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
|
||||
if(!h.cyl_count)
|
||||
return true;
|
||||
|
||||
std::function<void (const std::vector<uint32_t> &src, std::vector<uint32_t> &track)> converter;
|
||||
|
||||
if(!memcmp( h.sign, sign, 16)) {
|
||||
converter = [](const std::vector<uint32_t> &src, std::vector<uint32_t> &track) -> void {
|
||||
uint32_t ctime = 0;
|
||||
for(uint32_t mg : src) {
|
||||
ctime += mg & TIME_MASK;
|
||||
track.push_back((mg & MG_MASK) | ctime);
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
converter = [](const std::vector<uint32_t> &src, std::vector<uint32_t> &track) -> void {
|
||||
unsigned int cell_count = src.size();
|
||||
uint32_t mg = src[0] & MG_MASK;
|
||||
uint32_t wmg = src[cell_count - 1] & MG_MASK;
|
||||
if(mg != wmg && (mg == OLD_MG_A || mg == OLD_MG_B) && (wmg == OLD_MG_A && wmg == OLD_MG_B))
|
||||
// Flux change at 0, add it
|
||||
track.push_back(MG_F | 0);
|
||||
|
||||
uint32_t ctime = 0;
|
||||
for(unsigned int i=0; i != cell_count; i++) {
|
||||
uint32_t nmg = src[i] & MG_MASK;
|
||||
if(nmg == OLD_MG_N || nmg == OLD_MG_D) {
|
||||
track.push_back((nmg == OLD_MG_N ? MG_N : MG_D) | ctime);
|
||||
ctime += src[i] & TIME_MASK;
|
||||
track.push_back(MG_E | (ctime-1));
|
||||
nmg = 0xffffffff;
|
||||
} else {
|
||||
if(mg != 0xffffffff && mg != nmg)
|
||||
track.push_back(MG_F | ctime);
|
||||
ctime += src[i] & TIME_MASK;
|
||||
}
|
||||
mg = nmg;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> compressed;
|
||||
std::vector<uint32_t> uncompressed;
|
||||
|
||||
entry *ent = entries;
|
||||
for(unsigned int cyl=0; cyl <= (h.cyl_count - 1) << 2; cyl += 4 >> resolution)
|
||||
@ -143,31 +180,22 @@ bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int cell_count = ent->uncompressed_size/4;
|
||||
compressed.resize(ent->compressed_size);
|
||||
uncompressed.resize(cell_count);
|
||||
|
||||
io.read_at(ent->offset, &compressed[0], ent->compressed_size, actual);
|
||||
|
||||
unsigned int cell_count = ent->uncompressed_size/4;
|
||||
std::vector<uint32_t> &trackbuf = image->get_buffer(cyl >> 2, head, cyl & 3);;
|
||||
trackbuf.resize(cell_count);
|
||||
|
||||
uLongf size = ent->uncompressed_size;
|
||||
if(uncompress((Bytef *)&trackbuf[0], &size, &compressed[0], ent->compressed_size) != Z_OK) {
|
||||
if(uncompress((Bytef *)uncompressed.data(), &size, &compressed[0], ent->compressed_size) != Z_OK) {
|
||||
fprintf(stderr, "fail1\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t cur_time = 0;
|
||||
for(unsigned int i=0; i != cell_count; i++) {
|
||||
uint32_t next_cur_time = cur_time + (trackbuf[i] & TIME_MASK);
|
||||
trackbuf[i] = (trackbuf[i] & MG_MASK) | cur_time;
|
||||
cur_time = next_cur_time;
|
||||
}
|
||||
if(cur_time != 200000000) {
|
||||
fprintf(stderr, "fail2 %d\n", cur_time);
|
||||
return false;
|
||||
}
|
||||
std::vector<uint32_t> &trackbuf = image->get_buffer(cyl >> 2, head, cyl & 3);;
|
||||
trackbuf.clear();
|
||||
|
||||
converter(uncompressed, trackbuf);
|
||||
ent++;
|
||||
}
|
||||
|
||||
@ -214,13 +242,11 @@ bool mfi_format::save(util::random_read_write &io, const std::vector<uint32_t> &
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&precomp[0], &buffer[0], tsize*4);
|
||||
for(int j=0; j<tsize-1; j++)
|
||||
precomp[j] = (precomp[j] & floppy_image::MG_MASK) |
|
||||
((precomp[j+1] & floppy_image::TIME_MASK) -
|
||||
(precomp[j] & floppy_image::TIME_MASK));
|
||||
precomp[tsize-1] = (precomp[tsize-1] & floppy_image::MG_MASK) |
|
||||
(200000000 - (precomp[tsize-1] & floppy_image::TIME_MASK));
|
||||
uint32_t ctime = 0;
|
||||
for(int i=0; i != tsize; i++) {
|
||||
precomp[i] = (buffer[i] & MG_MASK) | ((buffer[i] & TIME_MASK) - ctime);
|
||||
ctime = buffer[i] & TIME_MASK;
|
||||
}
|
||||
|
||||
uLongf csize = max_track_size*4 + 1000;
|
||||
if(compress(postcomp.get(), &csize, (const Bytef *)precomp.get(), tsize*4) != Z_OK)
|
||||
|
@ -27,15 +27,21 @@ private:
|
||||
MG_MASK = 0xf0000000,
|
||||
MG_SHIFT = 28,
|
||||
|
||||
MG_A = (0 << MG_SHIFT),
|
||||
MG_B = (1 << MG_SHIFT),
|
||||
MG_N = (2 << MG_SHIFT),
|
||||
MG_D = (3 << MG_SHIFT),
|
||||
OLD_MG_A = (0 << MG_SHIFT),
|
||||
OLD_MG_B = (1 << MG_SHIFT),
|
||||
OLD_MG_N = (2 << MG_SHIFT),
|
||||
OLD_MG_D = (3 << MG_SHIFT),
|
||||
|
||||
MG_F = (0 << MG_SHIFT), //!< - 0, MG_F -> Flux orientation change
|
||||
MG_N = (1 << MG_SHIFT), //!< - 1, MG_N -> Non-magnetized zone (neutral)
|
||||
MG_D = (2 << MG_SHIFT), //!< - 2, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
|
||||
MG_E = (3 << MG_SHIFT), //!< - 3, MG_E -> End of zone
|
||||
|
||||
RESOLUTION_SHIFT = 30,
|
||||
CYLINDER_MASK = 0x3fffffff
|
||||
};
|
||||
|
||||
static const char sign_old[16];
|
||||
static const char sign[16];
|
||||
|
||||
struct header {
|
||||
|
@ -17,23 +17,20 @@
|
||||
// One = | 2237 | 6950 |
|
||||
// 0.5us ~= 143
|
||||
|
||||
void vtech_common_format::wbit(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, bool bit)
|
||||
void vtech_common_format::wbit(std::vector<uint32_t> &buffer, uint32_t &pos, bool bit)
|
||||
{
|
||||
buffer.push_back(pos | mg);
|
||||
mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
if(bit) {
|
||||
pos += 2237;
|
||||
buffer.push_back(pos | mg);
|
||||
mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
|
||||
buffer.push_back(pos | floppy_image::MG_F);
|
||||
pos += 6950;
|
||||
} else
|
||||
pos += 9187;
|
||||
}
|
||||
|
||||
void vtech_common_format::wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, uint8_t byte)
|
||||
void vtech_common_format::wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint8_t byte)
|
||||
{
|
||||
for(int i = 7; i >= 0; i--)
|
||||
wbit(buffer, pos, mg, (byte >> i) & 1);
|
||||
wbit(buffer, pos, (byte >> i) & 1);
|
||||
}
|
||||
|
||||
void vtech_common_format::image_to_flux(const std::vector<uint8_t> &bdata, floppy_image *image)
|
||||
@ -44,40 +41,39 @@ void vtech_common_format::image_to_flux(const std::vector<uint8_t> &bdata, flopp
|
||||
|
||||
for(int track = 0; track != 40; track ++) {
|
||||
uint32_t pos = 0;
|
||||
uint32_t mg = floppy_image::MG_A;
|
||||
std::vector<uint32_t> &buffer = image->get_buffer(track, 0);
|
||||
buffer.clear();
|
||||
image->set_write_splice_position(track, 0, 0);
|
||||
// One window of pad at the start to avoid problems with the write splice
|
||||
wbit(buffer, pos, mg, 0);
|
||||
wbit(buffer, pos, 0);
|
||||
|
||||
for(int sector = 0; sector != 16; sector ++) {
|
||||
uint8_t sid = sector_map[sector];
|
||||
for(int i=0; i != 7; i++)
|
||||
wbyte(buffer, pos, mg, 0x80);
|
||||
wbyte(buffer, pos, mg, 0x00);
|
||||
wbyte(buffer, pos, mg, 0xfe);
|
||||
wbyte(buffer, pos, mg, 0xe7);
|
||||
wbyte(buffer, pos, mg, 0x18);
|
||||
wbyte(buffer, pos, mg, 0xc3);
|
||||
wbyte(buffer, pos, mg, track);
|
||||
wbyte(buffer, pos, mg, sid);
|
||||
wbyte(buffer, pos, mg, track+sid);
|
||||
wbyte(buffer, pos, 0x80);
|
||||
wbyte(buffer, pos, 0x00);
|
||||
wbyte(buffer, pos, 0xfe);
|
||||
wbyte(buffer, pos, 0xe7);
|
||||
wbyte(buffer, pos, 0x18);
|
||||
wbyte(buffer, pos, 0xc3);
|
||||
wbyte(buffer, pos, track);
|
||||
wbyte(buffer, pos, sid);
|
||||
wbyte(buffer, pos, track+sid);
|
||||
for(int i=0; i != 5; i++)
|
||||
wbyte(buffer, pos, mg, 0x80);
|
||||
wbyte(buffer, pos, mg, 0x00);
|
||||
wbyte(buffer, pos, mg, 0xc3);
|
||||
wbyte(buffer, pos, mg, 0x18);
|
||||
wbyte(buffer, pos, mg, 0xe7);
|
||||
wbyte(buffer, pos, mg, 0xfe);
|
||||
wbyte(buffer, pos, 0x80);
|
||||
wbyte(buffer, pos, 0x00);
|
||||
wbyte(buffer, pos, 0xc3);
|
||||
wbyte(buffer, pos, 0x18);
|
||||
wbyte(buffer, pos, 0xe7);
|
||||
wbyte(buffer, pos, 0xfe);
|
||||
uint16_t chk = 0;
|
||||
const uint8_t *src = bdata.data() + 16*128*track + 128*sid;
|
||||
for(int i=0; i != 128; i++) {
|
||||
chk += src[i];
|
||||
wbyte(buffer, pos, mg, src[i]);
|
||||
wbyte(buffer, pos, src[i]);
|
||||
}
|
||||
wbyte(buffer, pos, mg, chk);
|
||||
wbyte(buffer, pos, mg, chk >> 8);
|
||||
wbyte(buffer, pos, chk);
|
||||
wbyte(buffer, pos, chk >> 8);
|
||||
}
|
||||
// Rest is just not formatted
|
||||
buffer.push_back(pos | floppy_image::MG_N);
|
||||
@ -95,29 +91,37 @@ std::vector<uint8_t> vtech_common_format::flux_to_image(floppy_image *image)
|
||||
continue;
|
||||
|
||||
std::vector<bool> bitstream;
|
||||
int lpos = -1;
|
||||
bool looped = !((buffer[sz-1] ^ buffer[0]) & floppy_image::MG_MASK);
|
||||
int cpos = looped ? sz-1 : 0;
|
||||
while(cpos != lpos) {
|
||||
int dt = looped && cpos == sz-1 ? (200000000 - (buffer[cpos] & floppy_image::TIME_MASK)) + (buffer[1] & floppy_image::TIME_MASK) :
|
||||
cpos == sz-1 ? 200000000 - (buffer[cpos] & floppy_image::TIME_MASK) :
|
||||
(buffer[cpos+1] & floppy_image::TIME_MASK) - (buffer[cpos] & floppy_image::TIME_MASK);
|
||||
int t = dt >= 9187 - 143 ? 0 :
|
||||
dt >= 2237 - 143 && dt <= 2237 + 143 ? 1 :
|
||||
2;
|
||||
if(t <= 1) {
|
||||
if(lpos == -1)
|
||||
lpos = cpos;
|
||||
bitstream.push_back(t);
|
||||
int cpos = 0;
|
||||
while((buffer[cpos] & floppy_image::MG_MASK) != floppy_image::MG_F) {
|
||||
cpos++;
|
||||
if(cpos == sz) {
|
||||
cpos = -1;
|
||||
break;
|
||||
}
|
||||
cpos += 1;
|
||||
if(cpos == sz)
|
||||
cpos = looped ? 1 : 0;
|
||||
}
|
||||
if(cpos == -1)
|
||||
continue;
|
||||
for(;;) {
|
||||
int npos = cpos;
|
||||
for(;;) {
|
||||
npos ++;
|
||||
if(npos == sz)
|
||||
npos = 0;
|
||||
if((buffer[npos] & floppy_image::MG_MASK) == floppy_image::MG_F)
|
||||
break;
|
||||
}
|
||||
int dt = (buffer[npos] & floppy_image::TIME_MASK) - (buffer[cpos] & floppy_image::TIME_MASK);
|
||||
if(dt < 0)
|
||||
cpos += 200000000;
|
||||
bitstream.push_back(dt < 9187 - 143);
|
||||
if(npos <= cpos)
|
||||
break;
|
||||
cpos = npos;
|
||||
}
|
||||
int mode = 0;
|
||||
looped = false;
|
||||
int pos = 0;
|
||||
int count = 0;
|
||||
bool looped = false;
|
||||
uint8_t *dest = nullptr;
|
||||
[[maybe_unused]] uint16_t checksum = 0;
|
||||
uint64_t buf = 0;
|
||||
|
@ -22,8 +22,8 @@ protected:
|
||||
static void image_to_flux(const std::vector<uint8_t> &bdata, floppy_image *image);
|
||||
static std::vector<uint8_t> flux_to_image(floppy_image *image);
|
||||
|
||||
static void wbit(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, bool bit);
|
||||
static void wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, uint8_t byte);
|
||||
static void wbit(std::vector<uint32_t> &buffer, uint32_t &pos, bool bit);
|
||||
static void wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint8_t byte);
|
||||
};
|
||||
|
||||
class vtech_bin_format : public vtech_common_format {
|
||||
|
Loading…
Reference in New Issue
Block a user