mirror of
https://github.com/holub/mame
synced 2025-04-25 17:56:43 +03:00
Sync with MESS, also placed back sdlmain change since it proved working on BSD (no whatsnew)
This commit is contained in:
parent
c7d7dad753
commit
6aadd7d787
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1481,7 +1481,9 @@ src/lib/formats/imd_dsk.c svneol=native#text/plain
|
|||||||
src/lib/formats/ioprocs.c svneol=native#text/plain
|
src/lib/formats/ioprocs.c svneol=native#text/plain
|
||||||
src/lib/formats/ioprocs.h svneol=native#text/plain
|
src/lib/formats/ioprocs.h svneol=native#text/plain
|
||||||
src/lib/formats/ipf_dsk.c svneol=native#text/plain
|
src/lib/formats/ipf_dsk.c svneol=native#text/plain
|
||||||
src/lib/formats/ipf_dsk.h -text svneol=native#text/plain
|
src/lib/formats/ipf_dsk.h svneol=native#text/plain
|
||||||
|
src/lib/formats/kc_cas.c svneol=native#text/plain
|
||||||
|
src/lib/formats/kc_cas.h svneol=native#text/plain
|
||||||
src/lib/formats/kim1_cas.c svneol=native#text/plain
|
src/lib/formats/kim1_cas.c svneol=native#text/plain
|
||||||
src/lib/formats/kim1_cas.h svneol=native#text/plain
|
src/lib/formats/kim1_cas.h svneol=native#text/plain
|
||||||
src/lib/formats/lviv_lvt.c svneol=native#text/plain
|
src/lib/formats/lviv_lvt.c svneol=native#text/plain
|
||||||
|
@ -559,7 +559,7 @@ void floppy_35_hd::setup_limits()
|
|||||||
|
|
||||||
|
|
||||||
floppy_525_dd::floppy_525_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
floppy_525_dd::floppy_525_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
floppy_image_device(mconfig, FLOPPY_525_DD, "3.5\" high density floppy drive", tag, owner, clock)
|
floppy_image_device(mconfig, FLOPPY_525_DD, "5.25\" double density floppy drive", tag, owner, clock)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,26 @@ void amiga_fdc::device_reset()
|
|||||||
live_abort();
|
live_abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dma_done()
|
||||||
|
{
|
||||||
|
dma_state = DMA_IDLE;
|
||||||
|
address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
|
||||||
|
amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dma_write(UINT16 value)
|
||||||
|
{
|
||||||
|
amiga_state *state = machine().driver_data<amiga_state>();
|
||||||
|
(*state->m_chip_ram_w)(state, dskpt, value);
|
||||||
|
|
||||||
|
dskpt += 2;
|
||||||
|
dsklen--;
|
||||||
|
if(dsklen & 0x3fff)
|
||||||
|
dma_state = DMA_RUNNING_BYTE_0;
|
||||||
|
else
|
||||||
|
dma_done();
|
||||||
|
}
|
||||||
|
|
||||||
void amiga_fdc::live_start()
|
void amiga_fdc::live_start()
|
||||||
{
|
{
|
||||||
cur_live.tm = machine().time();
|
cur_live.tm = machine().time();
|
||||||
@ -147,7 +167,7 @@ void amiga_fdc::live_run(attotime limit)
|
|||||||
live_delay(RUNNING_SYNCPOINT);
|
live_delay(RUNNING_SYNCPOINT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(dskbyt & 0x0400) {
|
if(dskbyt & 0x1000) {
|
||||||
if(cur_live.shift_reg != dsksync) {
|
if(cur_live.shift_reg != dsksync) {
|
||||||
live_delay(RUNNING_SYNCPOINT);
|
live_delay(RUNNING_SYNCPOINT);
|
||||||
return;
|
return;
|
||||||
@ -165,17 +185,26 @@ void amiga_fdc::live_run(attotime limit)
|
|||||||
if(cur_live.shift_reg == dsksync) {
|
if(cur_live.shift_reg == dsksync) {
|
||||||
if(adkcon & 0x0400) {
|
if(adkcon & 0x0400) {
|
||||||
if(dma_state == DMA_WAIT_START) {
|
if(dma_state == DMA_WAIT_START) {
|
||||||
dma_state = DMA_RUNNING_BYTE_0;
|
|
||||||
cur_live.bit_counter = 0;
|
cur_live.bit_counter = 0;
|
||||||
|
|
||||||
|
if(!(dsklen & 0x3fff))
|
||||||
|
dma_done();
|
||||||
|
else
|
||||||
|
dma_write(dsksync);
|
||||||
|
|
||||||
|
} else if(dma_state != DMA_IDLE) {
|
||||||
|
dma_write(dsksync);
|
||||||
|
cur_live.bit_counter = 0;
|
||||||
|
|
||||||
} else if(cur_live.bit_counter != 8)
|
} else if(cur_live.bit_counter != 8)
|
||||||
cur_live.bit_counter = 0;
|
cur_live.bit_counter = 0;
|
||||||
}
|
}
|
||||||
dskbyt |= 0x0400;
|
dskbyt |= 0x1000;
|
||||||
address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
|
address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
|
||||||
amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKSYN, 0xffff);
|
amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKSYN, 0xffff);
|
||||||
} else
|
} else
|
||||||
dskbyt &= ~0x0400;
|
dskbyt &= ~0x1000;
|
||||||
|
|
||||||
if(cur_live.bit_counter == 8) {
|
if(cur_live.bit_counter == 8) {
|
||||||
dskbyt = (dskbyt & 0xff00) | 0x8000 | (cur_live.shift_reg & 0xff);
|
dskbyt = (dskbyt & 0xff00) | 0x8000 | (cur_live.shift_reg & 0xff);
|
||||||
cur_live.bit_counter = 0;
|
cur_live.bit_counter = 0;
|
||||||
@ -192,19 +221,7 @@ void amiga_fdc::live_run(attotime limit)
|
|||||||
|
|
||||||
case DMA_RUNNING_BYTE_1: {
|
case DMA_RUNNING_BYTE_1: {
|
||||||
dma_value |= cur_live.shift_reg & 0xff;
|
dma_value |= cur_live.shift_reg & 0xff;
|
||||||
|
dma_write(dma_value);
|
||||||
amiga_state *state = machine().driver_data<amiga_state>();
|
|
||||||
(*state->m_chip_ram_w)(state, dskpt, dma_value);
|
|
||||||
|
|
||||||
dskpt += 2;
|
|
||||||
dsklen--;
|
|
||||||
if(dsklen & 0x3fff)
|
|
||||||
dma_state = DMA_RUNNING_BYTE_0;
|
|
||||||
else {
|
|
||||||
dma_state = DMA_IDLE;
|
|
||||||
address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
|
|
||||||
amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,9 +242,12 @@ bool amiga_fdc::dma_enabled()
|
|||||||
|
|
||||||
void amiga_fdc::dma_check()
|
void amiga_fdc::dma_check()
|
||||||
{
|
{
|
||||||
if(dma_enabled() && (dsklen & 0x3fff)) {
|
if(dma_enabled()) {
|
||||||
if(dma_state == IDLE)
|
if(dma_state == IDLE) {
|
||||||
dma_state = adkcon & 0x0400 ? DMA_WAIT_START : DMA_RUNNING_BYTE_0;
|
dma_state = adkcon & 0x0400 ? DMA_WAIT_START : DMA_RUNNING_BYTE_0;
|
||||||
|
if(dma_state == DMA_RUNNING_BYTE_0 && !(dsklen & 0x3fff))
|
||||||
|
dma_done();
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
dma_state = IDLE;
|
dma_state = IDLE;
|
||||||
}
|
}
|
||||||
@ -300,7 +320,9 @@ void amiga_fdc::dmacon_set(UINT16 data)
|
|||||||
|
|
||||||
UINT16 amiga_fdc::dskbytr_r()
|
UINT16 amiga_fdc::dskbytr_r()
|
||||||
{
|
{
|
||||||
return dskbyt;
|
UINT16 res = dskbyt;
|
||||||
|
dskbyt &= 0x7fff;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amiga_fdc::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
void amiga_fdc::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||||
|
@ -88,6 +88,8 @@ private:
|
|||||||
void index_callback(floppy_image_device *floppy, int state);
|
void index_callback(floppy_image_device *floppy, int state);
|
||||||
bool dma_enabled();
|
bool dma_enabled();
|
||||||
void dma_check();
|
void dma_check();
|
||||||
|
void dma_done();
|
||||||
|
void dma_write(UINT16 value);
|
||||||
|
|
||||||
void live_start();
|
void live_start();
|
||||||
void checkpoint();
|
void checkpoint();
|
||||||
|
@ -89,6 +89,38 @@ static FLOPPY_CONSTRUCT(hector_disc2_dsk800_construct)
|
|||||||
return basicdsk_construct(floppy, &geometry);
|
return basicdsk_construct(floppy, &geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For the 720Ko disk 3 1/2 inch disk for the mini disc unit !!:
|
||||||
|
512 bytes per sectors,
|
||||||
|
9 sector per track,
|
||||||
|
From sector =1 to sector 9,
|
||||||
|
80 tracks,
|
||||||
|
2 Head
|
||||||
|
This format can be extract from a real disc with anadisk (*.IMG format rename in *.HE7).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static FLOPPY_IDENTIFY(hector_minidisc_dsk_identify)
|
||||||
|
{
|
||||||
|
*vote = (floppy_image_size(floppy) == (2*70*9*512)) ? 100 : 0;
|
||||||
|
return FLOPPY_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FLOPPY_CONSTRUCT(hector_minidisc_dsk_construct)
|
||||||
|
{
|
||||||
|
struct basicdsk_geometry geometry;
|
||||||
|
memset(&geometry, 0, sizeof(geometry)); // 635904 octets
|
||||||
|
geometry.heads = 2;//2
|
||||||
|
geometry.first_sector_id = 1;
|
||||||
|
geometry.sector_length = 512;
|
||||||
|
geometry.tracks = 70;//69
|
||||||
|
geometry.sectors = 9;
|
||||||
|
return basicdsk_construct(floppy, &geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Specific for the mini disc unit */
|
||||||
|
LEGACY_FLOPPY_OPTIONS_START( hector_minidisc )
|
||||||
|
LEGACY_FLOPPY_OPTION( hector_dsk, "HMD", "hector mini disc floppy disk image 360Ko", hector_minidisc_dsk_identify, hector_minidisc_dsk_construct, NULL, NULL)
|
||||||
|
LEGACY_FLOPPY_OPTIONS_END
|
||||||
|
|
||||||
LEGACY_FLOPPY_OPTIONS_START( hector_disc2 )
|
LEGACY_FLOPPY_OPTIONS_START( hector_disc2 )
|
||||||
LEGACY_FLOPPY_OPTION( hector_dsk, "HE2", "hector disc2 floppy disk image 200K", hector_disc2_dsk200_identify, hector_disc2_dsk200_construct, NULL, NULL)
|
LEGACY_FLOPPY_OPTION( hector_dsk, "HE2", "hector disc2 floppy disk image 200K", hector_disc2_dsk200_identify, hector_disc2_dsk200_construct, NULL, NULL)
|
||||||
LEGACY_FLOPPY_OPTION( hector_dsk, "HE7", "hector disc2 floppy disk image 720K", hector_disc2_dsk720_identify, hector_disc2_dsk720_construct, NULL, NULL)
|
LEGACY_FLOPPY_OPTION( hector_dsk, "HE7", "hector disc2 floppy disk image 720K", hector_disc2_dsk720_identify, hector_disc2_dsk720_construct, NULL, NULL)
|
||||||
|
@ -15,5 +15,5 @@
|
|||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
LEGACY_FLOPPY_OPTIONS_EXTERN(hector_disc2);
|
LEGACY_FLOPPY_OPTIONS_EXTERN(hector_disc2);
|
||||||
|
LEGACY_FLOPPY_OPTIONS_EXTERN(hector_minidisc);
|
||||||
#endif /* HECT_DSK_H */
|
#endif /* HECT_DSK_H */
|
||||||
|
@ -273,15 +273,16 @@ void ipf_format::rotate(UINT32 *track, UINT32 offset, UINT32 size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ipf_format::mark_track_splice(UINT32 *t)
|
void ipf_format::mark_track_splice(UINT32 *track, UINT32 offset, UINT32 size)
|
||||||
{
|
{
|
||||||
for(int i=0; i<3; i++) {
|
for(int i=0; i<3; i++) {
|
||||||
UINT32 v = *t;
|
UINT32 pos = (offset + i) % size;
|
||||||
|
UINT32 v = track[pos];
|
||||||
if((v & floppy_image::MG_MASK) == MG_0)
|
if((v & floppy_image::MG_MASK) == MG_0)
|
||||||
v = (v & floppy_image::TIME_MASK) | MG_1;
|
v = (v & floppy_image::TIME_MASK) | MG_1;
|
||||||
else if((v & floppy_image::MG_MASK) == MG_1)
|
else if((v & floppy_image::MG_MASK) == MG_1)
|
||||||
v = (v & floppy_image::TIME_MASK) | MG_0;
|
v = (v & floppy_image::TIME_MASK) | MG_0;
|
||||||
*t++ = v;
|
track[pos] = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +407,7 @@ bool ipf_format::generate_track(track_info *t, floppy_image *image)
|
|||||||
|
|
||||||
data_pos[t->block_count] = pos;
|
data_pos[t->block_count] = pos;
|
||||||
|
|
||||||
mark_track_splice(track + splice_pos[t->block_count-1]);
|
mark_track_splice(track, splice_pos[t->block_count-1], t->size_cells);
|
||||||
|
|
||||||
if(!generate_timings(t, track, data_pos, gap_pos)) {
|
if(!generate_timings(t, track, data_pos, gap_pos)) {
|
||||||
global_free(track);
|
global_free(track);
|
||||||
|
@ -1,87 +1,87 @@
|
|||||||
#ifndef IPF_DSK_H_
|
#ifndef IPF_DSK_H_
|
||||||
#define IPF_DSK_H_
|
#define IPF_DSK_H_
|
||||||
|
|
||||||
#include "flopimg.h"
|
#include "flopimg.h"
|
||||||
|
|
||||||
class ipf_format : public floppy_image_format_t
|
class ipf_format : public floppy_image_format_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ipf_format();
|
ipf_format();
|
||||||
|
|
||||||
virtual int identify(io_generic *io);
|
virtual int identify(io_generic *io);
|
||||||
virtual bool load(io_generic *io, floppy_image *image);
|
virtual bool load(io_generic *io, floppy_image *image);
|
||||||
|
|
||||||
virtual const char *name() const;
|
virtual const char *name() const;
|
||||||
virtual const char *description() const;
|
virtual const char *description() const;
|
||||||
virtual const char *extensions() const;
|
virtual const char *extensions() const;
|
||||||
virtual bool supports_save() const;
|
virtual bool supports_save() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct track_info {
|
struct track_info {
|
||||||
UINT32 cylinder, head, type;
|
UINT32 cylinder, head, type;
|
||||||
UINT32 sigtype, process, reserved[3];
|
UINT32 sigtype, process, reserved[3];
|
||||||
UINT32 size_bytes, size_cells;
|
UINT32 size_bytes, size_cells;
|
||||||
UINT32 index_bytes, index_cells;
|
UINT32 index_bytes, index_cells;
|
||||||
UINT32 datasize_cells, gapsize_cells;
|
UINT32 datasize_cells, gapsize_cells;
|
||||||
UINT32 block_count, weak_bits;
|
UINT32 block_count, weak_bits;
|
||||||
|
|
||||||
UINT32 data_size_bits;
|
UINT32 data_size_bits;
|
||||||
|
|
||||||
bool info_set;
|
bool info_set;
|
||||||
|
|
||||||
const UINT8 *data;
|
const UINT8 *data;
|
||||||
UINT32 data_size;
|
UINT32 data_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
track_info *tinfos;
|
track_info *tinfos;
|
||||||
UINT32 tcount;
|
UINT32 tcount;
|
||||||
|
|
||||||
UINT32 type, release, revision;
|
UINT32 type, release, revision;
|
||||||
UINT32 encoder_type, encoder_revision, origin;
|
UINT32 encoder_type, encoder_revision, origin;
|
||||||
UINT32 min_cylinder, max_cylinder, min_head, max_head;
|
UINT32 min_cylinder, max_cylinder, min_head, max_head;
|
||||||
UINT32 credit_day, credit_time;
|
UINT32 credit_day, credit_time;
|
||||||
UINT32 platform[4], extra[5];
|
UINT32 platform[4], extra[5];
|
||||||
|
|
||||||
UINT32 crc32r(const UINT8 *data, UINT32 size);
|
UINT32 crc32r(const UINT8 *data, UINT32 size);
|
||||||
|
|
||||||
bool parse_info(const UINT8 *info);
|
bool parse_info(const UINT8 *info);
|
||||||
bool parse_imge(const UINT8 *imge);
|
bool parse_imge(const UINT8 *imge);
|
||||||
bool parse_data(const UINT8 *data, UINT32 &pos, UINT32 max_extra_size);
|
bool parse_data(const UINT8 *data, UINT32 &pos, UINT32 max_extra_size);
|
||||||
|
|
||||||
bool scan_one_tag(UINT8 *data, UINT32 size, UINT32 &pos, UINT8 *&tag, UINT32 &tsize);
|
bool scan_one_tag(UINT8 *data, UINT32 size, UINT32 &pos, UINT8 *&tag, UINT32 &tsize);
|
||||||
bool scan_all_tags(UINT8 *data, UINT32 size);
|
bool scan_all_tags(UINT8 *data, UINT32 size);
|
||||||
static UINT32 r32(const UINT8 *p);
|
static UINT32 r32(const UINT8 *p);
|
||||||
static UINT32 rb(const UINT8 *&p, int count);
|
static UINT32 rb(const UINT8 *&p, int count);
|
||||||
|
|
||||||
track_info *get_index(UINT32 idx);
|
track_info *get_index(UINT32 idx);
|
||||||
|
|
||||||
void track_write_raw(UINT32 *&track, const UINT8 *data, UINT32 cells, bool &context);
|
void track_write_raw(UINT32 *&track, const UINT8 *data, UINT32 cells, bool &context);
|
||||||
void track_write_mfm(UINT32 *&track, const UINT8 *data, UINT32 start_offset, UINT32 patlen, UINT32 cells, bool &context);
|
void track_write_mfm(UINT32 *&track, const UINT8 *data, UINT32 start_offset, UINT32 patlen, UINT32 cells, bool &context);
|
||||||
void track_write_weak(UINT32 *&track, UINT32 cells);
|
void track_write_weak(UINT32 *&track, UINT32 cells);
|
||||||
bool generate_block_data(const UINT8 *data, const UINT8 *dlimit, UINT32 *track, UINT32 *tlimit, bool &context);
|
bool generate_block_data(const UINT8 *data, const UINT8 *dlimit, UINT32 *track, UINT32 *tlimit, bool &context);
|
||||||
|
|
||||||
bool gap_description_to_reserved_size(const UINT8 *&data, const UINT8 *dlimit, UINT32 &res_size);
|
bool gap_description_to_reserved_size(const UINT8 *&data, const UINT8 *dlimit, UINT32 &res_size);
|
||||||
bool generate_gap_from_description(const UINT8 *&data, const UINT8 *dlimit, UINT32 *track, UINT32 size, bool pre, bool &context);
|
bool generate_gap_from_description(const UINT8 *&data, const UINT8 *dlimit, UINT32 *track, UINT32 size, bool pre, bool &context);
|
||||||
bool generate_block_gap_0(UINT32 gap_cells, UINT8 pattern, UINT32 &spos, UINT32 ipos, UINT32 *track, bool &context);
|
bool generate_block_gap_0(UINT32 gap_cells, UINT8 pattern, UINT32 &spos, UINT32 ipos, UINT32 *track, bool &context);
|
||||||
bool generate_block_gap_1(UINT32 gap_cells, UINT32 &spos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
bool generate_block_gap_1(UINT32 gap_cells, UINT32 &spos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
||||||
bool generate_block_gap_2(UINT32 gap_cells, UINT32 &spos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
bool generate_block_gap_2(UINT32 gap_cells, UINT32 &spos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
||||||
bool generate_block_gap_3(UINT32 gap_cells, UINT32 &spos, UINT32 ipos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
bool generate_block_gap_3(UINT32 gap_cells, UINT32 &spos, UINT32 ipos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
||||||
bool generate_block_gap(UINT32 gap_type, UINT32 gap_cells, UINT8 pattern, UINT32 &spos, UINT32 ipos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
bool generate_block_gap(UINT32 gap_type, UINT32 gap_cells, UINT8 pattern, UINT32 &spos, UINT32 ipos, const UINT8 *data, const UINT8 *dlimit, UINT32 *track, bool &context);
|
||||||
|
|
||||||
bool generate_block(track_info *t, UINT32 idx, UINT32 ipos, UINT32 *track, UINT32 &pos, UINT32 &dpos, UINT32 &gpos, UINT32 &spos, bool &context);
|
bool generate_block(track_info *t, UINT32 idx, UINT32 ipos, UINT32 *track, UINT32 &pos, UINT32 &dpos, UINT32 &gpos, UINT32 &spos, bool &context);
|
||||||
UINT32 block_compute_real_size(track_info *t);
|
UINT32 block_compute_real_size(track_info *t);
|
||||||
|
|
||||||
void timing_set(UINT32 *track, UINT32 start, UINT32 end, UINT32 time);
|
void timing_set(UINT32 *track, UINT32 start, UINT32 end, UINT32 time);
|
||||||
bool generate_timings(track_info *t, UINT32 *track, const UINT32 *data_pos, const UINT32 *gap_pos);
|
bool generate_timings(track_info *t, UINT32 *track, const UINT32 *data_pos, const UINT32 *gap_pos);
|
||||||
|
|
||||||
void rotate(UINT32 *track, UINT32 offset, UINT32 size);
|
void rotate(UINT32 *track, UINT32 offset, UINT32 size);
|
||||||
void mark_track_splice(UINT32 *t);
|
void mark_track_splice(UINT32 *track, UINT32 offset, UINT32 size);
|
||||||
bool generate_track(track_info *t, floppy_image *image);
|
bool generate_track(track_info *t, floppy_image *image);
|
||||||
bool generate_tracks(floppy_image *image);
|
bool generate_tracks(floppy_image *image);
|
||||||
|
|
||||||
bool parse(UINT8 *data, UINT32 size, floppy_image *image);
|
bool parse(UINT8 *data, UINT32 size, floppy_image *image);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const floppy_format_type FLOPPY_IPF_FORMAT;
|
extern const floppy_format_type FLOPPY_IPF_FORMAT;
|
||||||
|
|
||||||
#endif /*IPF_DSK_H_*/
|
#endif /*IPF_DSK_H_*/
|
||||||
|
390
src/lib/formats/kc_cas.c
Normal file
390
src/lib/formats/kc_cas.c
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
/********************************************************************
|
||||||
|
|
||||||
|
Support for KC85 cassette images
|
||||||
|
|
||||||
|
Supported formats:
|
||||||
|
- kcc: raw cassette image without ID and checksum
|
||||||
|
- tap: cassette image from KC-Emulator with head and ID
|
||||||
|
- tp2: cassette image with ID and checksum (130 bytes block)
|
||||||
|
- kcm: same as tp2 but without head
|
||||||
|
- sss: BASIC data without head (miss the first 11 bytes)
|
||||||
|
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
#include "kc_cas.h"
|
||||||
|
|
||||||
|
#define SMPLO -32768
|
||||||
|
#define SMPHI 32767
|
||||||
|
#define SILENCE 0
|
||||||
|
|
||||||
|
#define KC_WAV_FREQUENCY 44100
|
||||||
|
|
||||||
|
// from documentation
|
||||||
|
#define FREQ_BIT_0 2400
|
||||||
|
#define FREQ_BIT_1 1200
|
||||||
|
#define FREQ_SEPARATOR 600
|
||||||
|
|
||||||
|
// file formats
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
KC_IMAGE_KCC,
|
||||||
|
KC_IMAGE_TP2,
|
||||||
|
KC_IMAGE_TAP,
|
||||||
|
KC_IMAGE_KCM
|
||||||
|
};
|
||||||
|
|
||||||
|
// image size
|
||||||
|
static int kc_image_size;
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Generate one high-low cycle of sample data
|
||||||
|
********************************************************************/
|
||||||
|
INLINE int kc_cas_cycle(INT16 *buffer, int sample_pos, int len)
|
||||||
|
{
|
||||||
|
int num_samples = KC_WAV_FREQUENCY / (len * 2);
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int i=0; i<num_samples; i++)
|
||||||
|
buffer[ sample_pos + i ] = SMPHI;
|
||||||
|
|
||||||
|
for (int i=0; i<num_samples; i++)
|
||||||
|
buffer[ sample_pos + num_samples + i ] = SMPLO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_samples * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Generate n samples of silence
|
||||||
|
********************************************************************/
|
||||||
|
INLINE int kc_cas_silence(INT16 *buffer, int sample_pos, int len)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if ( buffer )
|
||||||
|
for( i = 0; i < len; i++)
|
||||||
|
buffer[ sample_pos + i ] = SILENCE;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Generate samples for 1 byte
|
||||||
|
********************************************************************/
|
||||||
|
INLINE int kc_cas_byte(INT16 *buffer, int sample_pos, UINT8 data)
|
||||||
|
{
|
||||||
|
int samples = 0;
|
||||||
|
|
||||||
|
// write the byte
|
||||||
|
for ( int i = 0; i < 8; i++ )
|
||||||
|
{
|
||||||
|
if ( data & 0x01 )
|
||||||
|
{
|
||||||
|
samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_BIT_1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_BIT_0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
data >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// byte separator
|
||||||
|
samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_SEPARATOR);
|
||||||
|
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kc_handle_cass(INT16 *buffer, const UINT8 *casdata, int type)
|
||||||
|
{
|
||||||
|
int data_pos = (type == KC_IMAGE_KCC || type == KC_IMAGE_KCM) ? 0 : 16;
|
||||||
|
int sample_count = 0;
|
||||||
|
int block_id = 1;
|
||||||
|
|
||||||
|
// 1 sec of silence at start
|
||||||
|
sample_count += kc_cas_silence(buffer, sample_count, KC_WAV_FREQUENCY);
|
||||||
|
|
||||||
|
// 8000 cycles of BIT_1 for synchronization
|
||||||
|
for (int i=0; i<8000; i++)
|
||||||
|
sample_count += kc_cas_cycle( buffer, sample_count, FREQ_BIT_1);
|
||||||
|
|
||||||
|
// on the entire file
|
||||||
|
while( data_pos < kc_image_size )
|
||||||
|
{
|
||||||
|
UINT8 checksum = 0;
|
||||||
|
|
||||||
|
// 200 cycles of BIT_1 every block
|
||||||
|
for (int i=0; i<200; i++)
|
||||||
|
sample_count += kc_cas_cycle( buffer, sample_count, FREQ_BIT_1);
|
||||||
|
|
||||||
|
// separator
|
||||||
|
sample_count += kc_cas_cycle( buffer, sample_count, FREQ_SEPARATOR);
|
||||||
|
|
||||||
|
// in TAP and TP2 file the first byte is the ID
|
||||||
|
if (type == KC_IMAGE_TAP || type == KC_IMAGE_TP2 || type == KC_IMAGE_KCM)
|
||||||
|
block_id = casdata[data_pos++];
|
||||||
|
|
||||||
|
// is the last block ?
|
||||||
|
if (data_pos + 128 >= kc_image_size && type == KC_IMAGE_KCC)
|
||||||
|
block_id = 0xff;
|
||||||
|
|
||||||
|
// write the block ID
|
||||||
|
sample_count += kc_cas_byte( buffer, sample_count, block_id );
|
||||||
|
|
||||||
|
// write the 128 bytes of the block
|
||||||
|
for (int i=0; i<128; i++)
|
||||||
|
{
|
||||||
|
UINT8 data = 0;
|
||||||
|
|
||||||
|
if (data_pos < kc_image_size)
|
||||||
|
data = casdata[data_pos++];
|
||||||
|
|
||||||
|
// calculate the checksum
|
||||||
|
checksum += data;
|
||||||
|
|
||||||
|
// write a byte
|
||||||
|
sample_count += kc_cas_byte( buffer, sample_count, data );
|
||||||
|
}
|
||||||
|
|
||||||
|
// TP2 and KCM files also have the checksum byte
|
||||||
|
if (type == KC_IMAGE_TP2 || type == KC_IMAGE_KCM)
|
||||||
|
checksum = casdata[data_pos++];
|
||||||
|
|
||||||
|
// 8bit checksum
|
||||||
|
sample_count += kc_cas_byte( buffer, sample_count, checksum );
|
||||||
|
|
||||||
|
// more TAP and TP2 can be combined into the same file
|
||||||
|
if ((type == KC_IMAGE_TAP || type == KC_IMAGE_TP2) && block_id == 0xff && data_pos < kc_image_size)
|
||||||
|
{
|
||||||
|
if (casdata[data_pos] == 0xc3 || casdata[data_pos] == 0x4b)
|
||||||
|
{
|
||||||
|
sample_count += kc_cas_silence(buffer, sample_count, KC_WAV_FREQUENCY/10);
|
||||||
|
|
||||||
|
data_pos += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sample_count += kc_cas_cycle( buffer, sample_count, FREQ_SEPARATOR);
|
||||||
|
|
||||||
|
// 1 sec of silence
|
||||||
|
sample_count += kc_cas_silence(buffer, sample_count, KC_WAV_FREQUENCY);
|
||||||
|
|
||||||
|
return sample_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int kc_handle_kcc(INT16 *buffer, const UINT8 *casdata)
|
||||||
|
{
|
||||||
|
return kc_handle_cass(buffer, casdata, KC_IMAGE_KCC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int kc_handle_tap(INT16 *buffer, const UINT8 *casdata)
|
||||||
|
{
|
||||||
|
if (!strncmp((const char *)(casdata + 1), "KC-TAPE by AF", 13))
|
||||||
|
{
|
||||||
|
return kc_handle_cass(buffer, casdata, KC_IMAGE_TAP);
|
||||||
|
}
|
||||||
|
else if (!strncmp((const char *)(casdata), "KC85", 4))
|
||||||
|
{
|
||||||
|
return kc_handle_cass(buffer, casdata, KC_IMAGE_TP2);
|
||||||
|
}
|
||||||
|
else if (casdata[0] == 0x01)
|
||||||
|
{
|
||||||
|
return kc_handle_cass(buffer, casdata, KC_IMAGE_KCM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CASSETTE_ERROR_INVALIDIMAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kc_handle_sss(INT16 *buffer, const UINT8 *casdata)
|
||||||
|
{
|
||||||
|
UINT8 *sss = (UINT8*)malloc(kc_image_size + 11);
|
||||||
|
|
||||||
|
// tries to generate the missing head
|
||||||
|
memset(sss + 0, 0xd3, 3);
|
||||||
|
memset(sss + 3, 0x20, 8);
|
||||||
|
memcpy(sss + 11, casdata, kc_image_size);
|
||||||
|
|
||||||
|
// set an arbitrary filename
|
||||||
|
sss[3] = 'A';
|
||||||
|
|
||||||
|
int retval = kc_handle_cass(buffer, sss, KC_IMAGE_KCC);
|
||||||
|
|
||||||
|
free(sss);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Generate samples for the tape image
|
||||||
|
********************************************************************/
|
||||||
|
static int kc_kcc_fill_wave(INT16 *buffer, int sample_count, UINT8 *bytes)
|
||||||
|
{
|
||||||
|
return kc_handle_kcc(buffer, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Calculate the number of samples needed for this tape image classical
|
||||||
|
********************************************************************/
|
||||||
|
static int kc_kcc_to_wav_size(const UINT8 *casdata, int caslen)
|
||||||
|
{
|
||||||
|
kc_image_size = caslen ;
|
||||||
|
|
||||||
|
return kc_handle_kcc( NULL, casdata );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct CassetteLegacyWaveFiller kc_kcc_legacy_fill_wave =
|
||||||
|
{
|
||||||
|
kc_kcc_fill_wave, /* fill_wave */
|
||||||
|
-1, /* chunk_size */
|
||||||
|
0, /* chunk_samples */
|
||||||
|
kc_kcc_to_wav_size, /* chunk_sample_calc */
|
||||||
|
KC_WAV_FREQUENCY, /* sample_frequency */
|
||||||
|
0, /* header_samples */
|
||||||
|
0 /* trailer_samples */
|
||||||
|
};
|
||||||
|
|
||||||
|
static casserr_t kc_kcc_identify(cassette_image *cassette, struct CassetteOptions *opts)
|
||||||
|
{
|
||||||
|
return cassette_legacy_identify(cassette, opts, &kc_kcc_legacy_fill_wave);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static casserr_t kc_kcc_load(cassette_image *cassette)
|
||||||
|
{
|
||||||
|
return cassette_legacy_construct(cassette, &kc_kcc_legacy_fill_wave);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct CassetteFormat kc_kcc_format =
|
||||||
|
{
|
||||||
|
"kcc,kcb",
|
||||||
|
kc_kcc_identify,
|
||||||
|
kc_kcc_load,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Generate samples for the tape image
|
||||||
|
********************************************************************/
|
||||||
|
static int kc_tap_fill_wave(INT16 *buffer, int sample_count, UINT8 *bytes)
|
||||||
|
{
|
||||||
|
return kc_handle_tap(buffer, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Calculate the number of samples needed for this tape image classical
|
||||||
|
********************************************************************/
|
||||||
|
static int kc_tap_to_wav_size(const UINT8 *casdata, int caslen)
|
||||||
|
{
|
||||||
|
kc_image_size = caslen ;
|
||||||
|
|
||||||
|
return kc_handle_tap( NULL, casdata );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct CassetteLegacyWaveFiller kc_tap_legacy_fill_wave =
|
||||||
|
{
|
||||||
|
kc_tap_fill_wave, /* fill_wave */
|
||||||
|
-1, /* chunk_size */
|
||||||
|
0, /* chunk_samples */
|
||||||
|
kc_tap_to_wav_size, /* chunk_sample_calc */
|
||||||
|
KC_WAV_FREQUENCY, /* sample_frequency */
|
||||||
|
0, /* header_samples */
|
||||||
|
0 /* trailer_samples */
|
||||||
|
};
|
||||||
|
|
||||||
|
static casserr_t kc_tap_identify(cassette_image *cassette, struct CassetteOptions *opts)
|
||||||
|
{
|
||||||
|
return cassette_legacy_identify(cassette, opts, &kc_tap_legacy_fill_wave);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static casserr_t kc_tap_load(cassette_image *cassette)
|
||||||
|
{
|
||||||
|
return cassette_legacy_construct(cassette, &kc_tap_legacy_fill_wave);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct CassetteFormat kc_tap_format =
|
||||||
|
{
|
||||||
|
"tap,853,854,855,tp2,kcm",
|
||||||
|
kc_tap_identify,
|
||||||
|
kc_tap_load,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Generate samples for the tape image
|
||||||
|
********************************************************************/
|
||||||
|
static int kc_sss_fill_wave(INT16 *buffer, int sample_count, UINT8 *bytes)
|
||||||
|
{
|
||||||
|
return kc_handle_sss(buffer, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Calculate the number of samples needed for this tape image classical
|
||||||
|
********************************************************************/
|
||||||
|
static int kc_sss_to_wav_size(const UINT8 *casdata, int caslen)
|
||||||
|
{
|
||||||
|
kc_image_size = caslen ;
|
||||||
|
|
||||||
|
return kc_handle_sss( NULL, casdata );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct CassetteLegacyWaveFiller kc_sss_legacy_fill_wave =
|
||||||
|
{
|
||||||
|
kc_sss_fill_wave, /* fill_wave */
|
||||||
|
-1, /* chunk_size */
|
||||||
|
0, /* chunk_samples */
|
||||||
|
kc_sss_to_wav_size, /* chunk_sample_calc */
|
||||||
|
KC_WAV_FREQUENCY, /* sample_frequency */
|
||||||
|
0, /* header_samples */
|
||||||
|
0 /* trailer_samples */
|
||||||
|
};
|
||||||
|
|
||||||
|
static casserr_t kc_sss_identify(cassette_image *cassette, struct CassetteOptions *opts)
|
||||||
|
{
|
||||||
|
return cassette_legacy_identify(cassette, opts, &kc_sss_legacy_fill_wave);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static casserr_t kc_sss_load(cassette_image *cassette)
|
||||||
|
{
|
||||||
|
return cassette_legacy_construct(cassette, &kc_sss_legacy_fill_wave);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct CassetteFormat kc_sss_format =
|
||||||
|
{
|
||||||
|
"sss",
|
||||||
|
kc_sss_identify,
|
||||||
|
kc_sss_load,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CASSETTE_FORMATLIST_START(kc_cassette_formats)
|
||||||
|
CASSETTE_FORMAT(kc_kcc_format)
|
||||||
|
CASSETTE_FORMAT(kc_tap_format)
|
||||||
|
CASSETTE_FORMAT(kc_sss_format)
|
||||||
|
CASSETTE_FORMATLIST_END
|
15
src/lib/formats/kc_cas.h
Normal file
15
src/lib/formats/kc_cas.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
|
||||||
|
kc_cas.h
|
||||||
|
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
#ifndef KC_CAS_H
|
||||||
|
#define KC_CAS_H
|
||||||
|
|
||||||
|
#include "cassimg.h"
|
||||||
|
|
||||||
|
CASSETTE_FORMATLIST_EXTERN(kc_cassette_formats);
|
||||||
|
|
||||||
|
#endif /* KC_CAS_H */
|
||||||
|
|
@ -119,6 +119,7 @@ FORMATSOBJS = \
|
|||||||
$(LIBOBJ)/formats/hect_tap.o \
|
$(LIBOBJ)/formats/hect_tap.o \
|
||||||
$(LIBOBJ)/formats/imd_dsk.o \
|
$(LIBOBJ)/formats/imd_dsk.o \
|
||||||
$(LIBOBJ)/formats/ipf_dsk.o \
|
$(LIBOBJ)/formats/ipf_dsk.o \
|
||||||
|
$(LIBOBJ)/formats/kc_cas.o \
|
||||||
$(LIBOBJ)/formats/kim1_cas.o \
|
$(LIBOBJ)/formats/kim1_cas.o \
|
||||||
$(LIBOBJ)/formats/lviv_lvt.o \
|
$(LIBOBJ)/formats/lviv_lvt.o \
|
||||||
$(LIBOBJ)/formats/msx_dsk.o \
|
$(LIBOBJ)/formats/msx_dsk.o \
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// standard includes
|
// standard includes
|
||||||
#ifdef MESS
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SDLMAME_OS2
|
#ifdef SDLMAME_OS2
|
||||||
#define INCL_DOS
|
#define INCL_DOS
|
||||||
|
Loading…
Reference in New Issue
Block a user