Experimental flux viewer, activate by #define FLUX_SCREEN 1 in floppy.cpp

This commit is contained in:
Olivier Galibert 2021-05-25 15:44:53 +02:00
parent d981a61ea6
commit 56db26dcbe
2 changed files with 200 additions and 1 deletions

View File

@ -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<uint32_t> &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
}

View File

@ -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<flux_per_pixel_info *> m_pixels[2];
uint32_t m_span;
uint8_t m_track;
uint8_t m_subtrack;
};
std::vector<flux_per_pixel_info> m_flux_per_pixel_infos;
std::vector<flux_per_combined_track_info> m_flux_per_combined_track_infos;
optional_device<screen_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) \