mirror of
https://github.com/holub/mame
synced 2025-07-01 00:09:18 +03:00
Experimental flux viewer, activate by #define FLUX_SCREEN 1 in floppy.cpp
This commit is contained in:
parent
d981a61ea6
commit
56db26dcbe
@ -24,6 +24,7 @@
|
|||||||
#include "formats/fs_unformatted.h"
|
#include "formats/fs_unformatted.h"
|
||||||
#include "formats/fsblk_vec.h"
|
#include "formats/fsblk_vec.h"
|
||||||
|
|
||||||
|
#include "screen.h"
|
||||||
#include "speaker.h"
|
#include "speaker.h"
|
||||||
#include "formats/imageutl.h"
|
#include "formats/imageutl.h"
|
||||||
#include "zippath.h"
|
#include "zippath.h"
|
||||||
@ -38,6 +39,8 @@
|
|||||||
|
|
||||||
#define PITCH_SEEK_SAMPLES 1
|
#define PITCH_SEEK_SAMPLES 1
|
||||||
|
|
||||||
|
#define FLUX_SCREEN 0
|
||||||
|
|
||||||
#define FLOPSND_TAG "floppysound"
|
#define FLOPSND_TAG "floppysound"
|
||||||
|
|
||||||
// device type definition
|
// device type definition
|
||||||
@ -261,7 +264,8 @@ floppy_image_device::floppy_image_device(const machine_config &mconfig, device_t
|
|||||||
image_dirty(false),
|
image_dirty(false),
|
||||||
ready_counter(0),
|
ready_counter(0),
|
||||||
m_make_sound(false),
|
m_make_sound(false),
|
||||||
m_sound_out(nullptr)
|
m_sound_out(nullptr),
|
||||||
|
m_flux_screen(*this, "flux")
|
||||||
{
|
{
|
||||||
extension_list[0] = '\0';
|
extension_list[0] = '\0';
|
||||||
m_err = IMAGE_ERROR_INVALIDIMAGE;
|
m_err = IMAGE_ERROR_INVALIDIMAGE;
|
||||||
@ -475,6 +479,27 @@ void floppy_image_device::device_start()
|
|||||||
save_item(NAME(image_dirty));
|
save_item(NAME(image_dirty));
|
||||||
save_item(NAME(ready_counter));
|
save_item(NAME(ready_counter));
|
||||||
save_item(NAME(phases));
|
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()
|
void floppy_image_device::device_reset()
|
||||||
@ -592,9 +617,143 @@ image_init_result floppy_image_device::call_load()
|
|||||||
if (!cur_load_cb.isnull())
|
if (!cur_load_cb.isnull())
|
||||||
return cur_load_cb(this);
|
return cur_load_cb(this);
|
||||||
|
|
||||||
|
flux_image_prepare();
|
||||||
return image_init_result::PASS;
|
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()
|
void floppy_image_device::call_unload()
|
||||||
{
|
{
|
||||||
cache_clear();
|
cache_clear();
|
||||||
@ -650,6 +809,8 @@ image_init_result floppy_image_device::call_create(int format_type, util::option
|
|||||||
|
|
||||||
init_floppy_load(true);
|
init_floppy_load(true);
|
||||||
|
|
||||||
|
flux_image_prepare();
|
||||||
|
|
||||||
return image_init_result::PASS;
|
return image_init_result::PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1207,6 +1368,8 @@ void floppy_image_device::write_flux(const attotime &start, const attotime &end,
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf.resize(cells);
|
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)
|
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();
|
SPEAKER(config, FLOPSPK).front_center();
|
||||||
FLOPPYSOUND(config, FLOPSND_TAG, 44100).add_route(ALL_OUTPUTS, FLOPSPK, 0.5);
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,6 +266,35 @@ protected:
|
|||||||
// Sound
|
// Sound
|
||||||
bool m_make_sound;
|
bool m_make_sound;
|
||||||
floppy_sound_device* m_sound_out;
|
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) \
|
#define DECLARE_FLOPPY_IMAGE_DEVICE(Type, Name, Interface) \
|
||||||
|
Loading…
Reference in New Issue
Block a user