diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp index c73b7c87cb0..e0212fff4c2 100644 --- a/src/devices/imagedev/floppy.cpp +++ b/src/devices/imagedev/floppy.cpp @@ -24,6 +24,7 @@ #include "formats/fs_unformatted.h" #include "formats/fsblk_vec.h" +#include "screen.h" #include "speaker.h" #include "formats/imageutl.h" #include "zippath.h" @@ -38,6 +39,8 @@ #define PITCH_SEEK_SAMPLES 1 +#define FLUX_SCREEN 0 + #define FLOPSND_TAG "floppysound" // device type definition @@ -261,7 +264,8 @@ floppy_image_device::floppy_image_device(const machine_config &mconfig, device_t image_dirty(false), ready_counter(0), m_make_sound(false), - m_sound_out(nullptr) + m_sound_out(nullptr), + m_flux_screen(*this, "flux") { extension_list[0] = '\0'; m_err = IMAGE_ERROR_INVALIDIMAGE; @@ -475,6 +479,27 @@ void floppy_image_device::device_start() save_item(NAME(image_dirty)); save_item(NAME(ready_counter)); save_item(NAME(phases)); + + m_flux_per_pixel_infos.resize(flux_screen_sx*flux_screen_sy); + flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data(); + for(int y = 0; y != flux_screen_sy; y++) { + int head = y >= flux_screen_sy / 2 ? 1 : 0; + int yc = (flux_screen_sy/2-1)/2 + (flux_screen_sy/2)*head; + int dy = y - yc; + for(int x = 0; x != flux_screen_sx; x++) { + const int xc = (flux_screen_sx - 1)/2; + int dx = x - xc; + int r = int(sqrt(dx*dx + dy*dy) + 0.5); + ppi->m_r = r; + if(r > flux_max_r || r < flux_min_r) + ppi->m_position = 0xffffffff; + else + ppi->m_position = int((200e6 / 2 / M_PI) * atan2(dy, dx) + 100000000.5) % 200000000; + ppi->m_combined_track = 0; + ppi->m_color = 0; + ppi ++; + } + } } void floppy_image_device::device_reset() @@ -592,9 +617,143 @@ image_init_result floppy_image_device::call_load() if (!cur_load_cb.isnull()) return cur_load_cb(this); + flux_image_prepare(); return image_init_result::PASS; } +void floppy_image_device::flux_image_prepare() +{ + int tracks = 0, heads = 0, rez = 0; + image->get_maximal_geometry(tracks, heads); + rez = image->get_resolution(); + + int trackm = (tracks - 1) << rez; + int tmask = (1 << rez) - 1; + + m_flux_per_combined_track_infos.clear(); + m_flux_per_combined_track_infos.resize(trackm+1); + for(int track = 0; track <= trackm; track++) { + int refr = 200 + (trackm - 0.5 - track) * 290 / (trackm+1) + 200; + int span = int((200e6 / 2 / M_PI) / refr); + m_flux_per_combined_track_infos[track].m_span = span; + m_flux_per_combined_track_infos[track].m_track = track >> rez; + m_flux_per_combined_track_infos[track].m_subtrack = track & tmask; + } + + flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data(); + for(int head = 0; head != heads; head++) + for(unsigned int i=0; i != flux_screen_sx*flux_screen_sy/2; i++) { + if(ppi->m_position != 0xffffffff) { + int trk = (trackm + 1) * (flux_max_r - ppi->m_r) / (flux_max_r - flux_min_r + 1); + ppi->m_combined_track = trk; + m_flux_per_combined_track_infos[trk].m_pixels[head].push_back(ppi); + } + ppi++; + } + + for(auto &t : m_flux_per_combined_track_infos) { + std::sort(t.m_pixels[0].begin(), t.m_pixels[0].end(), [](const flux_per_pixel_info *a, const flux_per_pixel_info *b) -> bool { return a->m_position < b->m_position; }); + if(heads == 2) + std::sort(t.m_pixels[1].begin(), t.m_pixels[1].end(), [](const flux_per_pixel_info *a, const flux_per_pixel_info *b) -> bool { return a->m_position < b->m_position; }); + } + + for(int head = 0; head != heads; head++) + for(int track = 0; track <= trackm; track++) + flux_image_compute_for_track(track, head); +} + +void floppy_image_device::flux_image_compute_for_track(int track, int head) +{ + auto *pcti = m_flux_per_combined_track_infos.data() + track; + const std::vector &buffer = image->get_buffer(pcti->m_track, head, pcti->m_subtrack); + int sz = buffer.size(); + if(!sz) { + for(flux_per_pixel_info *p : m_flux_per_combined_track_infos[track].m_pixels[head]) + p->m_color = 255; + return; + } + + int spos = pcti->m_pixels[head][0]->m_position - pcti->m_span + 200000000; + int bpos = sz; + while(bpos && (buffer[bpos-1] & floppy_image::TIME_MASK) < spos) + bpos --; + if(bpos == sz) + bpos = 0; + + int pspos = spos; + for(flux_per_pixel_info *p : m_flux_per_combined_track_infos[track].m_pixels[head]) { + int spos = p->m_position - pcti->m_span; + int epos = p->m_position + pcti->m_span; + if(spos < 0) + spos += 200000000; + if(epos >= 200000000) + epos -= 200000000; + + if(spos < pspos) + bpos = 0; + while(bpos != sz-1 && (buffer[bpos+1] & floppy_image::TIME_MASK) < spos) + bpos ++; + + int bpos2 = spos < epos ? bpos : 0; + while(bpos2 != sz-1 && (buffer[bpos2+1] & floppy_image::TIME_MASK) < epos) + bpos2 ++; + + int count; + if(bpos <= bpos2) + count = bpos2 - bpos; + else { + count = (sz - 1 - bpos) + bpos2; + if((buffer[0] ^ buffer[sz-1]) & floppy_image::MG_MASK) + count ++; + } + + count *= 5; + if(count > 255) + count = 255; + p->m_color = 255 - count; + pspos = spos; + } +} + +uint32_t floppy_image_device::flux_screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if(image.get()) { + int ctrack = ((cyl << 2) | subcyl) >> (2 - image->get_resolution()); + if(mon) + ctrack = -1; + for(int y = cliprect.min_y; y <= cliprect.max_y; y++) { + int head = y >= flux_screen_sy / 2; + flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data() + y * flux_screen_sx + cliprect.min_x; + uint32_t *p = &bitmap.pix(y, cliprect.min_x); + for(int x = cliprect.min_x; x <= cliprect.max_x; x++) { + if(ppi->m_position == 0xffffffff) + *p++ = 0; + else { + u32 color = 0x010101 * ppi->m_color; + if(ppi->m_combined_track == ctrack && head == ss) + color &= 0x0000ff; + *p++ = color; + } + ppi++; + } + } + } else { + for(int y = cliprect.min_y; y <= cliprect.max_y; y++) { + flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data() + y * flux_screen_sx + cliprect.min_x; + uint32_t *p = &bitmap.pix(y, cliprect.min_x); + for(int x = cliprect.min_x; x <= cliprect.max_x; x++) { + if(ppi->m_position == 0xffffffff) + *p++ = 0; + else + *p++ = 0x404040; + ppi++; + } + } + } + + return 0; +} + void floppy_image_device::call_unload() { cache_clear(); @@ -650,6 +809,8 @@ image_init_result floppy_image_device::call_create(int format_type, util::option init_floppy_load(true); + flux_image_prepare(); + return image_init_result::PASS; } @@ -1207,6 +1368,8 @@ void floppy_image_device::write_flux(const attotime &start, const attotime &end, } buf.resize(cells); + + flux_image_compute_for_track(((cyl << 2) | subcyl) >> (2 - image->get_resolution()), ss); } void floppy_image_device::write_zone(uint32_t *buf, int &cells, int &index, uint32_t spos, uint32_t epos, uint32_t mg) @@ -1706,6 +1869,13 @@ void floppy_image_device::device_add_mconfig(machine_config &config) { SPEAKER(config, FLOPSPK).front_center(); FLOPPYSOUND(config, FLOPSND_TAG, 44100).add_route(ALL_OUTPUTS, FLOPSPK, 0.5); + +#if FLUX_SCREEN + SCREEN(config, m_flux_screen, SCREEN_TYPE_RASTER); + m_flux_screen->set_screen_update(FUNC(floppy_image_device::flux_screen_update)); + m_flux_screen->set_raw(30*(flux_screen_sx+1)*(flux_screen_sy+1), flux_screen_sx+1, 0, flux_screen_sx, flux_screen_sy+1, 0, flux_screen_sy); + m_flux_screen->set_physical_aspect(1, 2); +#endif } diff --git a/src/devices/imagedev/floppy.h b/src/devices/imagedev/floppy.h index ea3eea381cc..01ae6d5d594 100644 --- a/src/devices/imagedev/floppy.h +++ b/src/devices/imagedev/floppy.h @@ -266,6 +266,35 @@ protected: // Sound bool m_make_sound; floppy_sound_device* m_sound_out; + + // Flux visualization + struct flux_per_pixel_info { + uint32_t m_position; // 0-199999999 Angular position in the track, 0xffffffff if not in the floppy image + uint16_t m_r; // Distance from the center + uint8_t m_combined_track; // No need to store head, it's y >= flux_screen_sy/2 + uint8_t m_color; // Computed gray level from the flux counts + }; + + struct flux_per_combined_track_info { + std::vector m_pixels[2]; + uint32_t m_span; + uint8_t m_track; + uint8_t m_subtrack; + }; + + std::vector m_flux_per_pixel_infos; + std::vector m_flux_per_combined_track_infos; + + optional_device m_flux_screen; + + static constexpr int flux_screen_sx = 501; + static constexpr int flux_screen_sy = 1002; + static constexpr int flux_min_r = 100; + static constexpr int flux_max_r = 245; + + void flux_image_prepare(); + void flux_image_compute_for_track(int track, int head); + uint32_t flux_screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect); }; #define DECLARE_FLOPPY_IMAGE_DEVICE(Type, Name, Interface) \