Added support for TD0 (Teledisk) floppy images;
Fixed support for Japanese HDI hard disk images; Attempt to mix DOS 4.x DOSSHELL mouse issues.
This commit is contained in:
@@ -5,7 +5,7 @@ WINDRES = windres.exe
|
|||||||
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
|
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
|
||||||
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
|
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
|
||||||
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
|
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
|
||||||
device.o disc.o disc_86f.o disc_fdi.o disc_img_86box.o disc_random.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
device.o disc.o disc_86f.o disc_fdi.o disc_img_86box.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
||||||
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
|
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
|
||||||
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
||||||
|
@@ -5,7 +5,7 @@ WINDRES = windres.exe
|
|||||||
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
|
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
|
||||||
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
|
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
|
||||||
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \
|
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \
|
||||||
device.o disc.o disc_86f.o disc_fdi.o disc_img_86box.o disc_random.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
device.o disc.o disc_86f.o disc_fdi.o disc_img_86box.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
||||||
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
|
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
|
||||||
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include "disc_fdi.h"
|
#include "disc_fdi.h"
|
||||||
#include "disc_img.h"
|
#include "disc_img.h"
|
||||||
#include "disc_86f.h"
|
#include "disc_86f.h"
|
||||||
|
#include "disc_td0.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "fdd.h"
|
#include "fdd.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
@@ -72,6 +73,7 @@ loaders[]=
|
|||||||
{"FLP", img_load, img_close, -1},
|
{"FLP", img_load, img_close, -1},
|
||||||
{"IMG", img_load, img_close, -1},
|
{"IMG", img_load, img_close, -1},
|
||||||
{"IMA", img_load, img_close, -1},
|
{"IMA", img_load, img_close, -1},
|
||||||
|
{"TD0", td0_load, td0_close, -1},
|
||||||
{"VFD", img_load, img_close, -1},
|
{"VFD", img_load, img_close, -1},
|
||||||
{"XDF", img_load, img_close, -1},
|
{"XDF", img_load, img_close, -1},
|
||||||
{"FDI", fdi_load, fdi_close, -1},
|
{"FDI", fdi_load, fdi_close, -1},
|
||||||
|
11
src/disc.h
11
src/disc.h
@@ -138,4 +138,13 @@ uint8_t* d86f_track_data(int drive, int side);
|
|||||||
uint8_t* d86f_track_layout(int drive, int side);
|
uint8_t* d86f_track_layout(int drive, int side);
|
||||||
|
|
||||||
uint16_t d86f_prepare_pretrack(int drive, int side, int iso, int write_data);
|
uint16_t d86f_prepare_pretrack(int drive, int side, int iso, int write_data);
|
||||||
uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int write_data, int gap2, int gap3, int limit);
|
uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int write_data, int gap2, int gap3, int limit, int deleted, int bad_crc);
|
||||||
|
|
||||||
|
int gap3_sizes[5][8][256];
|
||||||
|
|
||||||
|
void null_writeback(int drive);
|
||||||
|
void null_poll_write_data(int drive, int side, uint16_t pos, uint8_t data);
|
||||||
|
int null_format_conditions(int drive);
|
||||||
|
void d86f_unregister(int drive);
|
||||||
|
|
||||||
|
void d86f_reset_index_hole_pos(int drive, int side);
|
||||||
|
@@ -262,7 +262,7 @@ void null_poll_write_data(int drive, int side, uint16_t pos, uint8_t data)
|
|||||||
|
|
||||||
int null_format_conditions(int drive)
|
int null_format_conditions(int drive)
|
||||||
{
|
{
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void d86f_unregister(int drive)
|
void d86f_unregister(int drive)
|
||||||
@@ -1252,7 +1252,7 @@ void d86f_reset_index_hole_pos(int drive, int side)
|
|||||||
d86f[drive].index_hole_pos[side] = 0;
|
d86f[drive].index_hole_pos[side] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int write_data, int gap2, int gap3, int limit)
|
uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int write_data, int gap2, int gap3, int limit, int deleted, int bad_crc)
|
||||||
{
|
{
|
||||||
uint16_t i = pos;
|
uint16_t i = pos;
|
||||||
uint16_t j = 0;
|
uint16_t j = 0;
|
||||||
@@ -1346,8 +1346,8 @@ uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint
|
|||||||
if (write_data)
|
if (write_data)
|
||||||
{
|
{
|
||||||
if (!mfm) d86f[drive].calc_crc.word = 0xffff;
|
if (!mfm) d86f[drive].calc_crc.word = 0xffff;
|
||||||
d86f_memset(d86f[drive].track_data[side] + i, 0xFB, 1, i, rs, limit);
|
d86f_memset(d86f[drive].track_data[side] + i, deleted ? 0xF8 : 0xFB, 1, i, rs, limit);
|
||||||
d86f_calccrc(drive, 0xFB);
|
d86f_calccrc(drive, deleted ? 0xF8 : 0xFB);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
if ((i >= rs) && limit) return 0;
|
if ((i >= rs) && limit) return 0;
|
||||||
@@ -1365,8 +1365,17 @@ uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint
|
|||||||
d86f_memset(d86f[drive].track_layout[side] + i, BYTE_DATA_CRC, 2, i, rs, limit);
|
d86f_memset(d86f[drive].track_layout[side] + i, BYTE_DATA_CRC, 2, i, rs, limit);
|
||||||
if (write_data)
|
if (write_data)
|
||||||
{
|
{
|
||||||
d86f[drive].track_data[side][i] = d86f[drive].calc_crc.bytes[1];
|
if (bad_crc)
|
||||||
d86f[drive].track_data[side][(i + 1) % rs] = d86f[drive].calc_crc.bytes[0];
|
{
|
||||||
|
/* If sector has to be prepared with a bad CRC, just reverse the bytes and toggle the LSB of the first byte, and the CRC will automatically be wrong. */
|
||||||
|
d86f[drive].track_data[side][i] = d86f[drive].calc_crc.bytes[0] ^ 1;
|
||||||
|
d86f[drive].track_data[side][(i + 1) % rs] = d86f[drive].calc_crc.bytes[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d86f[drive].track_data[side][i] = d86f[drive].calc_crc.bytes[1];
|
||||||
|
d86f[drive].track_data[side][(i + 1) % rs] = d86f[drive].calc_crc.bytes[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i += 2;
|
i += 2;
|
||||||
if ((i >= rs) && limit) return 0;
|
if ((i >= rs) && limit) return 0;
|
||||||
@@ -1398,7 +1407,7 @@ void d86f_prepare_track_layout(int drive, int side)
|
|||||||
for (j = 0; j < sc; j++)
|
for (j = 0; j < sc; j++)
|
||||||
{
|
{
|
||||||
/* Always limit to prevent wraparounds when formatting! */
|
/* Always limit to prevent wraparounds when formatting! */
|
||||||
i = d86f_prepare_sector(drive, side, i, NULL, NULL, dtl, 0, real_gap2_len, real_gap3_len, 1);
|
i = d86f_prepare_sector(drive, side, i, NULL, NULL, dtl, 0, real_gap2_len, real_gap3_len, 1, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1888,7 +1897,7 @@ int d86f_poll_check_notfound(int drive)
|
|||||||
/* The index hole has been hit twice and we're still in a find state.
|
/* The index hole has been hit twice and we're still in a find state.
|
||||||
This means sector finding has failed for whatever reason.
|
This means sector finding has failed for whatever reason.
|
||||||
Abort with sector not found and set state to idle. */
|
Abort with sector not found and set state to idle. */
|
||||||
// pclog("d86f_poll(): Sector not found (%i %i %i %i) (%i, %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive));
|
pclog("d86f_poll(): Sector not found (%i %i %i %i) (%i, %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive));
|
||||||
fdc_notfound();
|
fdc_notfound();
|
||||||
d86f[drive].state = STATE_IDLE;
|
d86f[drive].state = STATE_IDLE;
|
||||||
d86f[drive].index_count = 0;
|
d86f[drive].index_count = 0;
|
||||||
|
@@ -1,16 +1,7 @@
|
|||||||
/* Copyright holders: Sarah Walker
|
/* Copyright holders: Sarah Walker, Kiririn
|
||||||
see COPYING for more details
|
see COPYING for more details
|
||||||
*/
|
*/
|
||||||
void img_init();
|
void img_init();
|
||||||
void img_load(int drive, char *fn);
|
void img_load(int drive, char *fn);
|
||||||
void img_close(int drive);
|
void img_close(int drive);
|
||||||
void img_seek(int drive, int track);
|
void img_seek(int drive, int track);
|
||||||
void img_readsector(int drive, int sector, int track, int side, int density);
|
|
||||||
void img_writesector(int drive, int sector, int track, int side, int density);
|
|
||||||
void img_readaddress(int drive, int sector, int side, int density);
|
|
||||||
void img_format(int drive, int sector, int side, int density);
|
|
||||||
int img_hole(int drive);
|
|
||||||
double img_byteperiod(int drive);
|
|
||||||
void img_stop(int drive);
|
|
||||||
void img_poll();
|
|
||||||
int img_realtrack(int track, int drive);
|
|
||||||
|
@@ -6,7 +6,6 @@
|
|||||||
#include "fdd.h"
|
#include "fdd.h"
|
||||||
#include "disc.h"
|
#include "disc.h"
|
||||||
#include "disc_img.h"
|
#include "disc_img.h"
|
||||||
#include "disc_sector.h"
|
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
@@ -121,7 +120,7 @@ static uint8_t rates[6] = { 2, 2, 1, 4, 0, 3 };
|
|||||||
|
|
||||||
static uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 };
|
static uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 };
|
||||||
|
|
||||||
static int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
|
int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
|
||||||
[0][2][18] = 0x6C,
|
[0][2][18] = 0x6C,
|
||||||
[0][2][19] = 0x48,
|
[0][2][19] = 0x48,
|
||||||
[0][2][20] = 0x2A,
|
[0][2][20] = 0x2A,
|
||||||
@@ -156,15 +155,6 @@ static int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
|
|||||||
[4][3][10] = 0x74
|
[4][3][10] = 0x74
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Needed for formatting! */
|
|
||||||
int img_realtrack(int drive, int track)
|
|
||||||
{
|
|
||||||
if ((img[drive].tracks <= 43) && fdd_doublestep_40(drive))
|
|
||||||
track /= 2;
|
|
||||||
|
|
||||||
return track;
|
|
||||||
}
|
|
||||||
|
|
||||||
void img_writeback(int drive);
|
void img_writeback(int drive);
|
||||||
|
|
||||||
static int sector_size_code(int sector_size)
|
static int sector_size_code(int sector_size)
|
||||||
@@ -225,6 +215,8 @@ void img_load(int drive, char *fn)
|
|||||||
ext[2] = fn[strlen(fn) - 1] | 0x60;
|
ext[2] = fn[strlen(fn) - 1] | 0x60;
|
||||||
ext[3] = 0;
|
ext[3] = 0;
|
||||||
|
|
||||||
|
d86f_unregister(drive);
|
||||||
|
|
||||||
writeprot[drive] = 0;
|
writeprot[drive] = 0;
|
||||||
img[drive].f = fopen(fn, "rb+");
|
img[drive].f = fopen(fn, "rb+");
|
||||||
if (!img[drive].f)
|
if (!img[drive].f)
|
||||||
@@ -240,8 +232,6 @@ void img_load(int drive, char *fn)
|
|||||||
}
|
}
|
||||||
fwriteprot[drive] = writeprot[drive];
|
fwriteprot[drive] = writeprot[drive];
|
||||||
|
|
||||||
d86f_unregister(drive);
|
|
||||||
|
|
||||||
if (strcmp(ext, "fdi") == 0)
|
if (strcmp(ext, "fdi") == 0)
|
||||||
{
|
{
|
||||||
/* This is a Japanese FDI image, so let's read the header */
|
/* This is a Japanese FDI image, so let's read the header */
|
||||||
@@ -406,6 +396,7 @@ void img_load(int drive, char *fn)
|
|||||||
|
|
||||||
void img_close(int drive)
|
void img_close(int drive)
|
||||||
{
|
{
|
||||||
|
d86f_unregister(drive);
|
||||||
if (img[drive].f)
|
if (img[drive].f)
|
||||||
fclose(img[drive].f);
|
fclose(img[drive].f);
|
||||||
img[drive].f = NULL;
|
img[drive].f = NULL;
|
||||||
@@ -460,7 +451,7 @@ void img_seek(int drive, int track)
|
|||||||
img[drive].sector_pos_side[side][sr] = side;
|
img[drive].sector_pos_side[side][sr] = side;
|
||||||
img[drive].sector_pos[side][sr] = (sr - 1) * ssize;
|
img[drive].sector_pos[side][sr] = (sr - 1) * ssize;
|
||||||
// if (img[drive].dmf) pclog("DMF: %i %i %i %i | %i %04X\n", id[0], id[1], id[2], id[3], side, (sr - 1) * ssize);
|
// if (img[drive].dmf) pclog("DMF: %i %i %i %i | %i %04X\n", id[0], id[1], id[2], id[3], side, (sr - 1) * ssize);
|
||||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[side][(sr - 1) * ssize], ssize, 1, img[drive].gap2_size, img[drive].gap3_size, 0);
|
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[side][(sr - 1) * ssize], ssize, 1, img[drive].gap2_size, img[drive].gap3_size, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -517,14 +508,14 @@ void img_seek(int drive, int track)
|
|||||||
{
|
{
|
||||||
id[3] = 2;
|
id[3] = 2;
|
||||||
// pclog("XDF Track 0: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
// pclog("XDF Track 0: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
||||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0);
|
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
id[3] = id[2] & 7;
|
id[3] = id[2] & 7;
|
||||||
// pclog("XDF Track X: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
// pclog("XDF Track X: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
||||||
ssize = (128 << id[3]);
|
ssize = (128 << id[3]);
|
||||||
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0);
|
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
885
src/disc_td0.c
Normal file
885
src/disc_td0.c
Normal file
@@ -0,0 +1,885 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Miodrag Milanovic,Kiririn (translation to C and port to 86Box)
|
||||||
|
/*********************************************************************
|
||||||
|
|
||||||
|
formats/td0_dsk.c
|
||||||
|
|
||||||
|
TD0 disk images
|
||||||
|
|
||||||
|
*********************************************************************/
|
||||||
|
/*
|
||||||
|
* Based on Japanese version 29-NOV-1988
|
||||||
|
* LZSS coded by Haruhiko OKUMURA
|
||||||
|
* Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
|
||||||
|
* Edited and translated to English by Kenji RIKITAKE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "fdc.h"
|
||||||
|
#include "fdd.h"
|
||||||
|
#include "disc.h"
|
||||||
|
#include "disc_td0.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define BUFSZ 512 // new input buffer
|
||||||
|
|
||||||
|
/* LZSS Parameters */
|
||||||
|
|
||||||
|
#define N 4096 /* Size of string buffer */
|
||||||
|
#define F 60 /* Size of look-ahead buffer */
|
||||||
|
#define THRESHOLD 2
|
||||||
|
#define NIL N /* End of tree's node */
|
||||||
|
|
||||||
|
|
||||||
|
/* Huffman coding parameters */
|
||||||
|
|
||||||
|
#define N_CHAR (256 - THRESHOLD + F)
|
||||||
|
/* character code (= 0..N_CHAR-1) */
|
||||||
|
#define T (N_CHAR * 2 - 1) /* Size of table */
|
||||||
|
#define R (T - 1) /* root position */
|
||||||
|
#define MAX_FREQ 0x8000
|
||||||
|
/* update when cumulative frequency */
|
||||||
|
/* reaches to this value */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t r,
|
||||||
|
bufcnt,bufndx,bufpos, // string buffer
|
||||||
|
// the following to allow block reads from input in next_word()
|
||||||
|
ibufcnt,ibufndx; // input buffer counters
|
||||||
|
uint8_t inbuf[BUFSZ]; // input buffer
|
||||||
|
} tdlzhuf;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FILE *floppy_file;
|
||||||
|
uint64_t floppy_file_offset;
|
||||||
|
|
||||||
|
tdlzhuf tdctl;
|
||||||
|
uint8_t text_buf[N + F - 1];
|
||||||
|
uint16_t freq[T + 1]; /* cumulative freq table */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pointing parent nodes.
|
||||||
|
* area [T..(T + N_CHAR - 1)] are pointers for leaves
|
||||||
|
*/
|
||||||
|
int16_t prnt[T + N_CHAR];
|
||||||
|
|
||||||
|
/* pointing children nodes (son[], son[] + 1)*/
|
||||||
|
int16_t son[T];
|
||||||
|
|
||||||
|
uint16_t getbuf;
|
||||||
|
uint8_t getlen;
|
||||||
|
} td0dsk_t;
|
||||||
|
|
||||||
|
//static td0dsk_t td0dsk;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t track;
|
||||||
|
uint8_t head;
|
||||||
|
uint8_t sector;
|
||||||
|
uint8_t size;
|
||||||
|
uint8_t deleted;
|
||||||
|
uint8_t bad_crc;
|
||||||
|
uint8_t *data;
|
||||||
|
} td0_sector_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
int tracks;
|
||||||
|
int sides;
|
||||||
|
uint16_t disk_flags;
|
||||||
|
uint16_t default_track_flags;
|
||||||
|
uint16_t side_flags[256][2];
|
||||||
|
uint8_t track_in_file[256][2];
|
||||||
|
td0_sector_t sects[256][2][256];
|
||||||
|
uint8_t track_spt[256][2];
|
||||||
|
uint8_t gap3_len;
|
||||||
|
uint16_t current_side_flags[2];
|
||||||
|
int track;
|
||||||
|
int current_sector_index[2];
|
||||||
|
} td0_t;
|
||||||
|
|
||||||
|
td0_t td0[2];
|
||||||
|
|
||||||
|
|
||||||
|
void floppy_image_read(int drive, char *buffer, uint32_t offset, uint32_t len)
|
||||||
|
{
|
||||||
|
fseek(td0[drive].f, offset, SEEK_SET);
|
||||||
|
fread(buffer, 1, len, td0[drive].f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int td0_dsk_identify(int drive)
|
||||||
|
{
|
||||||
|
uint8_t header[2];
|
||||||
|
|
||||||
|
floppy_image_read(drive, header, 0, 2);
|
||||||
|
if (header[0]=='T' && header[1]=='D') {
|
||||||
|
return 1;
|
||||||
|
} else if (header[0]=='t' && header[1]=='d') {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int td0_state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size)
|
||||||
|
{
|
||||||
|
uint32_t image_size = 0;
|
||||||
|
fseek(state->floppy_file, 0, SEEK_END);
|
||||||
|
image_size = ftell(state->floppy_file);
|
||||||
|
if (size > image_size - state->floppy_file_offset) {
|
||||||
|
size = image_size - state->floppy_file_offset;
|
||||||
|
}
|
||||||
|
fseek(state->floppy_file, state->floppy_file_offset, SEEK_SET);
|
||||||
|
fread(buf, 1, size, state->floppy_file);
|
||||||
|
state->floppy_file_offset += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tables for encoding/decoding upper 6 bits of
|
||||||
|
* sliding dictionary pointer
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* decoder table */
|
||||||
|
static const uint8_t d_code[256] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||||
|
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
||||||
|
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
|
||||||
|
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
|
||||||
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
|
||||||
|
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||||
|
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
|
||||||
|
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
|
||||||
|
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
|
||||||
|
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
|
||||||
|
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
|
||||||
|
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
|
||||||
|
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
|
||||||
|
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
|
||||||
|
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
|
||||||
|
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
|
||||||
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||||
|
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t d_len[256] = {
|
||||||
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||||
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||||
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||||
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||||
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||||
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||||
|
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
int td0_state_next_word(td0dsk_t *state)
|
||||||
|
{
|
||||||
|
if(state->tdctl.ibufndx >= state->tdctl.ibufcnt)
|
||||||
|
{
|
||||||
|
state->tdctl.ibufndx = 0;
|
||||||
|
state->tdctl.ibufcnt = td0_state_data_read(state, state->tdctl.inbuf,BUFSZ);
|
||||||
|
if(state->tdctl.ibufcnt <= 0)
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
while (state->getlen <= 8) { // typically reads a word at a time
|
||||||
|
state->getbuf |= state->tdctl.inbuf[state->tdctl.ibufndx++] << (8 - state->getlen);
|
||||||
|
state->getlen += 8;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int td0_state_GetBit(td0dsk_t *state) /* get one bit */
|
||||||
|
{
|
||||||
|
int16_t i;
|
||||||
|
if(td0_state_next_word(state) < 0)
|
||||||
|
return(-1);
|
||||||
|
i = state->getbuf;
|
||||||
|
state->getbuf <<= 1;
|
||||||
|
state->getlen--;
|
||||||
|
if(i < 0)
|
||||||
|
return(1);
|
||||||
|
else
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int td0_state_GetByte(td0dsk_t *state) /* get a byte */
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
if(td0_state_next_word(state) != 0)
|
||||||
|
return(-1);
|
||||||
|
i = state->getbuf;
|
||||||
|
state->getbuf <<= 8;
|
||||||
|
state->getlen -= 8;
|
||||||
|
i = i >> 8;
|
||||||
|
return((int) i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* initialize freq tree */
|
||||||
|
|
||||||
|
void td0_state_StartHuff(td0dsk_t *state)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < N_CHAR; i++) {
|
||||||
|
state->freq[i] = 1;
|
||||||
|
state->son[i] = i + T;
|
||||||
|
state->prnt[i + T] = i;
|
||||||
|
}
|
||||||
|
i = 0; j = N_CHAR;
|
||||||
|
while (j <= R) {
|
||||||
|
state->freq[j] = state->freq[i] + state->freq[i + 1];
|
||||||
|
state->son[j] = i;
|
||||||
|
state->prnt[i] = state->prnt[i + 1] = j;
|
||||||
|
i += 2; j++;
|
||||||
|
}
|
||||||
|
state->freq[T] = 0xffff;
|
||||||
|
state->prnt[R] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* reconstruct freq tree */
|
||||||
|
|
||||||
|
void td0_state_reconst(td0dsk_t *state)
|
||||||
|
{
|
||||||
|
int16_t i, j, k;
|
||||||
|
uint16_t f, l;
|
||||||
|
|
||||||
|
/* halven cumulative freq for leaf nodes */
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < T; i++) {
|
||||||
|
if (state->son[i] >= T) {
|
||||||
|
state->freq[j] = (state->freq[i] + 1) / 2;
|
||||||
|
state->son[j] = state->son[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* make a tree : first, connect children nodes */
|
||||||
|
for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
|
||||||
|
k = i + 1;
|
||||||
|
f = state->freq[j] = state->freq[i] + state->freq[k];
|
||||||
|
for (k = j - 1; f < state->freq[k]; k--) {};
|
||||||
|
k++;
|
||||||
|
l = (j - k) * 2;
|
||||||
|
|
||||||
|
/* movmem() is Turbo-C dependent
|
||||||
|
rewritten to memmove() by Kenji */
|
||||||
|
|
||||||
|
/* movmem(&freq[k], &freq[k + 1], l); */
|
||||||
|
(void)memmove(&state->freq[k + 1], &state->freq[k], l);
|
||||||
|
state->freq[k] = f;
|
||||||
|
/* movmem(&son[k], &son[k + 1], l); */
|
||||||
|
(void)memmove(&state->son[k + 1], &state->son[k], l);
|
||||||
|
state->son[k] = i;
|
||||||
|
}
|
||||||
|
/* connect parent nodes */
|
||||||
|
for (i = 0; i < T; i++) {
|
||||||
|
if ((k = state->son[i]) >= T) {
|
||||||
|
state->prnt[k] = i;
|
||||||
|
} else {
|
||||||
|
state->prnt[k] = state->prnt[k + 1] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* update freq tree */
|
||||||
|
|
||||||
|
void td0_state_update(td0dsk_t *state, int c)
|
||||||
|
{
|
||||||
|
int i, j, k, l;
|
||||||
|
|
||||||
|
if (state->freq[R] == MAX_FREQ) {
|
||||||
|
td0_state_reconst(state);
|
||||||
|
}
|
||||||
|
c = state->prnt[c + T];
|
||||||
|
do {
|
||||||
|
k = ++state->freq[c];
|
||||||
|
|
||||||
|
/* swap nodes to keep the tree freq-ordered */
|
||||||
|
if (k > state->freq[l = c + 1]) {
|
||||||
|
while (k > state->freq[++l]) {};
|
||||||
|
l--;
|
||||||
|
state->freq[c] = state->freq[l];
|
||||||
|
state->freq[l] = k;
|
||||||
|
|
||||||
|
i = state->son[c];
|
||||||
|
state->prnt[i] = l;
|
||||||
|
if (i < T) state->prnt[i + 1] = l;
|
||||||
|
|
||||||
|
j = state->son[l];
|
||||||
|
state->son[l] = i;
|
||||||
|
|
||||||
|
state->prnt[j] = c;
|
||||||
|
if (j < T) state->prnt[j + 1] = c;
|
||||||
|
state->son[c] = j;
|
||||||
|
|
||||||
|
c = l;
|
||||||
|
}
|
||||||
|
} while ((c = state->prnt[c]) != 0); /* do it until reaching the root */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t td0_state_DecodeChar(td0dsk_t *state)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint16_t c;
|
||||||
|
|
||||||
|
c = state->son[R];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start searching tree from the root to leaves.
|
||||||
|
* choose node #(son[]) if input bit == 0
|
||||||
|
* else choose #(son[]+1) (input bit == 1)
|
||||||
|
*/
|
||||||
|
while (c < T) {
|
||||||
|
if((ret = td0_state_GetBit(state)) < 0)
|
||||||
|
return(-1);
|
||||||
|
c += (unsigned) ret;
|
||||||
|
c = state->son[c];
|
||||||
|
}
|
||||||
|
c -= T;
|
||||||
|
td0_state_update(state, c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t td0_state_DecodePosition(td0dsk_t *state)
|
||||||
|
{
|
||||||
|
int16_t bit;
|
||||||
|
uint16_t i, j, c;
|
||||||
|
|
||||||
|
/* decode upper 6 bits from given table */
|
||||||
|
if((bit=td0_state_GetByte(state)) < 0)
|
||||||
|
return(-1);
|
||||||
|
i = (uint16_t) bit;
|
||||||
|
c = (uint16_t)d_code[i] << 6;
|
||||||
|
j = d_len[i];
|
||||||
|
|
||||||
|
/* input lower 6 bits directly */
|
||||||
|
j -= 2;
|
||||||
|
while (j--) {
|
||||||
|
if((bit = td0_state_GetBit(state)) < 0)
|
||||||
|
return(-1);
|
||||||
|
i = (i << 1) + bit;
|
||||||
|
}
|
||||||
|
return(c | (i & 0x3f));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DeCompression
|
||||||
|
|
||||||
|
split out initialization code to init_Decode()
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void td0_state_init_Decode(td0dsk_t *state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
state->getbuf = 0;
|
||||||
|
state->getlen = 0;
|
||||||
|
state->tdctl.ibufcnt= state->tdctl.ibufndx = 0; // input buffer is empty
|
||||||
|
state->tdctl.bufcnt = 0;
|
||||||
|
td0_state_StartHuff(state);
|
||||||
|
for (i = 0; i < N - F; i++)
|
||||||
|
state->text_buf[i] = ' ';
|
||||||
|
state->tdctl.r = N - F;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int td0_state_Decode(td0dsk_t *state, uint8_t *buf, int len) /* Decoding/Uncompressing */
|
||||||
|
{
|
||||||
|
int16_t c,pos;
|
||||||
|
int count; // was an unsigned long, seems unnecessary
|
||||||
|
for (count = 0; count < len; ) {
|
||||||
|
if(state->tdctl.bufcnt == 0) {
|
||||||
|
if((c = td0_state_DecodeChar(state)) < 0)
|
||||||
|
return(count); // fatal error
|
||||||
|
if (c < 256) {
|
||||||
|
*(buf++) = c;
|
||||||
|
state->text_buf[state->tdctl.r++] = c;
|
||||||
|
state->tdctl.r &= (N - 1);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if((pos = td0_state_DecodePosition(state)) < 0)
|
||||||
|
return(count); // fatal error
|
||||||
|
state->tdctl.bufpos = (state->tdctl.r - pos - 1) & (N - 1);
|
||||||
|
state->tdctl.bufcnt = c - 255 + THRESHOLD;
|
||||||
|
state->tdctl.bufndx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // still chars from last string
|
||||||
|
while( state->tdctl.bufndx < state->tdctl.bufcnt && count < len ) {
|
||||||
|
c = state->text_buf[(state->tdctl.bufpos + state->tdctl.bufndx) & (N - 1)];
|
||||||
|
*(buf++) = c;
|
||||||
|
state->tdctl.bufndx++;
|
||||||
|
state->text_buf[state->tdctl.r++] = c;
|
||||||
|
state->tdctl.r &= (N - 1);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
// reset bufcnt after copy string from text_buf[]
|
||||||
|
if(state->tdctl.bufndx >= state->tdctl.bufcnt)
|
||||||
|
state->tdctl.bufndx = state->tdctl.bufcnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(count); // count == len, success
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
|
||||||
|
formats/td0_dsk.h
|
||||||
|
|
||||||
|
Teledisk disk images
|
||||||
|
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
int td0_initialize(int drive);
|
||||||
|
|
||||||
|
void td0_seek(int drive, int track);
|
||||||
|
|
||||||
|
void td0_init()
|
||||||
|
{
|
||||||
|
memset(td0, 0, sizeof(td0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void d86f_register_td0(int drive);
|
||||||
|
|
||||||
|
static const int rates[3] = { 2, 1, 0 };
|
||||||
|
const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
|
||||||
|
uint8_t imagebuf[4*1024*1024];
|
||||||
|
uint8_t processed_buf[4*1024*1024];
|
||||||
|
uint8_t header[12];
|
||||||
|
|
||||||
|
void td0_load(int drive, char *fn)
|
||||||
|
{
|
||||||
|
int track;
|
||||||
|
int head;
|
||||||
|
int fm;
|
||||||
|
int offset = 0;
|
||||||
|
int ret = 0;
|
||||||
|
const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
|
||||||
|
|
||||||
|
d86f_unregister(drive);
|
||||||
|
|
||||||
|
writeprot[drive] = 1;
|
||||||
|
td0[drive].f = fopen(fn, "rb");
|
||||||
|
if (!td0[drive].f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fwriteprot[drive] = writeprot[drive];
|
||||||
|
|
||||||
|
ret = td0_dsk_identify(drive);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
pclog("TD0: Not a valid Teledisk image\n");
|
||||||
|
fclose(td0[drive].f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pclog("TD0: Valid Teledisk image\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(imagebuf, 0, 4*1024*1024);
|
||||||
|
memset(processed_buf, 0, 4*1024*1024);
|
||||||
|
ret = td0_initialize(drive);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
pclog("TD0: Failed to initialize\n");
|
||||||
|
fclose(td0[drive].f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pclog("TD0: Initialized successfully\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
d86f_register_td0(drive);
|
||||||
|
|
||||||
|
drives[drive].seek = td0_seek;
|
||||||
|
|
||||||
|
d86f_common_handlers(drive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void td0_close(int drive)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
int k = 0;
|
||||||
|
d86f_unregister(drive);
|
||||||
|
memset(imagebuf, 0, 4*1024*1024);
|
||||||
|
memset(processed_buf, 0, 4*1024*1024);
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
for (k = 0; k < 256; k++)
|
||||||
|
{
|
||||||
|
td0[drive].sects[i][j][k].data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (td0[drive].f)
|
||||||
|
fclose(td0[drive].f);
|
||||||
|
td0[drive].f = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int td0_initialize(int drive)
|
||||||
|
{
|
||||||
|
int track;
|
||||||
|
int head;
|
||||||
|
int fm;
|
||||||
|
int track_count = 0;
|
||||||
|
int head_count = 0;
|
||||||
|
int track_spt;
|
||||||
|
int offset = 0;
|
||||||
|
int ret = 0;
|
||||||
|
int gap3_len = 0;
|
||||||
|
int rate = 0;
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
int temp_rate = 0;
|
||||||
|
uint32_t file_size;
|
||||||
|
uint16_t len;
|
||||||
|
uint16_t rep;
|
||||||
|
td0dsk_t disk_decode;
|
||||||
|
uint8_t *hs;
|
||||||
|
uint16_t size;
|
||||||
|
uint8_t *dbuf = processed_buf;
|
||||||
|
|
||||||
|
if (!td0[drive].f)
|
||||||
|
{
|
||||||
|
pclog("TD0: Attempted to initialize without loading a file first\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(td0[drive].f, 0, SEEK_SET);
|
||||||
|
fread(header, 1, 12, td0[drive].f);
|
||||||
|
head_count = header[9];
|
||||||
|
|
||||||
|
if(header[0] == 't')
|
||||||
|
{
|
||||||
|
pclog("TD0: File is compressed\n");
|
||||||
|
disk_decode.floppy_file = td0[drive].f;
|
||||||
|
td0_state_init_Decode(&disk_decode);
|
||||||
|
disk_decode.floppy_file_offset = 12;
|
||||||
|
td0_state_Decode(&disk_decode, imagebuf, max_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pclog("TD0: File is uncompressed\n");
|
||||||
|
fseek(td0[drive].f, 0, SEEK_END);
|
||||||
|
file_size = ftell(td0[drive].f);
|
||||||
|
fseek(td0[drive].f, 12, SEEK_SET);
|
||||||
|
fread(imagebuf, 1, file_size - 12, td0[drive].f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(header[7] & 0x80)
|
||||||
|
offset = 10 + imagebuf[2] + (imagebuf[3] << 8);
|
||||||
|
|
||||||
|
track_spt = imagebuf[offset];
|
||||||
|
if(track_spt == 255) // Empty file?
|
||||||
|
{
|
||||||
|
pclog("TD0: File has no tracks\n");
|
||||||
|
fclose(td0[drive].f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We determine RPM from the drive type as well as we possibly can. */
|
||||||
|
switch(header[6])
|
||||||
|
{
|
||||||
|
case 0: /* 5.25" 2DD in 2HD drive: 360 rpm */
|
||||||
|
case 2: /* 5.25" 2HD: 360 rpm */
|
||||||
|
case 5: /* 8 " 2?D: 360 rpm */
|
||||||
|
td0[drive].default_track_flags = 0x20;
|
||||||
|
break;
|
||||||
|
case 1: /* 5.25" 2DD: 300 rpm */
|
||||||
|
case 3: /* 3.5 " 2DD: 300 rpm */
|
||||||
|
case 4: /* 3.5 " 2HD: 300 rpm */
|
||||||
|
case 6: /* 3.5 " 2ED?: 300 rpm */
|
||||||
|
td0[drive].default_track_flags = 0x00;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rate = (header[5] & 0x7f) >= 3 ? 0 : rates[header[5] & 0x7f];
|
||||||
|
td0[drive].default_track_flags |= rate;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
memset(td0[drive].side_flags[i], 0, 4);
|
||||||
|
memset(td0[drive].track_in_file[i], 0, 2);
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
memset(td0[drive].sects[i][j], 0, sizeof(td0_sector_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(track_spt != 255)
|
||||||
|
{
|
||||||
|
track = imagebuf[offset + 1];
|
||||||
|
head = imagebuf[offset + 2] & 1;
|
||||||
|
fm = (header[5] & 0x80) || (imagebuf[offset + 2] & 0x80); // ?
|
||||||
|
td0[drive].side_flags[track][head] = td0[drive].default_track_flags | (fm ? 0 : 8);
|
||||||
|
td0[drive].track_in_file[track][head] = 1;
|
||||||
|
offset += 4;
|
||||||
|
for(i = 0; i < track_spt; i++)
|
||||||
|
{
|
||||||
|
hs = &imagebuf[offset];
|
||||||
|
size;
|
||||||
|
offset += 6;
|
||||||
|
|
||||||
|
td0[drive].sects[track][head][i].track = hs[0];
|
||||||
|
td0[drive].sects[track][head][i].head = hs[1];
|
||||||
|
td0[drive].sects[track][head][i].sector = hs[2];
|
||||||
|
td0[drive].sects[track][head][i].size = hs[3];
|
||||||
|
td0[drive].sects[track][head][i].deleted = (hs[4] & 4) == 4;
|
||||||
|
td0[drive].sects[track][head][i].bad_crc = (hs[4] & 2) == 2;
|
||||||
|
td0[drive].sects[track][head][i].data = dbuf;
|
||||||
|
|
||||||
|
size = 128 << hs[3];
|
||||||
|
|
||||||
|
if(hs[4] & 0x30)
|
||||||
|
{
|
||||||
|
memset(dbuf, 0, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset += 3;
|
||||||
|
int j, k;
|
||||||
|
switch(hs[8])
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
pclog("TD0: Image uses an unsupported sector data encoding\n");
|
||||||
|
fclose(td0[drive].f);
|
||||||
|
return 0;
|
||||||
|
case 0:
|
||||||
|
memcpy(dbuf, &imagebuf[offset], size);
|
||||||
|
offset += size;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
offset += 4;
|
||||||
|
k = (hs[9] + (hs[10] << 8)) * 2;
|
||||||
|
k = (k <= size) ? k : size;
|
||||||
|
for(j = 0; j < k; j += 2)
|
||||||
|
{
|
||||||
|
dbuf[j] = hs[11];
|
||||||
|
dbuf[j + 1] = hs[12];
|
||||||
|
}
|
||||||
|
if(k < size)
|
||||||
|
memset(&(dbuf[k]), 0, size - k);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
k = 0;
|
||||||
|
while(k < size)
|
||||||
|
{
|
||||||
|
len = imagebuf[offset];
|
||||||
|
rep = imagebuf[offset + 1];
|
||||||
|
offset += 2;
|
||||||
|
if(!len)
|
||||||
|
{
|
||||||
|
memcpy(&(dbuf[k]), &imagebuf[offset], rep);
|
||||||
|
offset += rep;
|
||||||
|
k += rep;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = (1 << len);
|
||||||
|
rep = len * rep;
|
||||||
|
rep = ((rep + k) <= size) ? rep : (size - k);
|
||||||
|
for(j = 0; j < rep; j += len)
|
||||||
|
memcpy(&(dbuf[j + k]), &imagebuf[offset], len);
|
||||||
|
k += rep;
|
||||||
|
offset += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbuf += size;
|
||||||
|
}
|
||||||
|
track_count = track;
|
||||||
|
|
||||||
|
track_spt = imagebuf[offset];
|
||||||
|
|
||||||
|
td0[drive].track_spt[track][head] = track_spt;
|
||||||
|
}
|
||||||
|
|
||||||
|
td0[drive].tracks = track_count + 1;
|
||||||
|
|
||||||
|
temp_rate = rate;
|
||||||
|
if ((td0[drive].default_track_flags & 0x27) == 0x20) temp_rate = 4;
|
||||||
|
td0[drive].gap3_len = gap3_sizes[temp_rate][td0[drive].sects[0][0][0].size][td0[drive].track_spt[0][0]];
|
||||||
|
// pclog("GAP3 length for %i %i %i is %i\n", temp_rate, td0[drive].sects[0][0][0].size, td0[drive].track_spt[0][0], td0[drive].gap3_len);
|
||||||
|
if (!td0[drive].gap3_len)
|
||||||
|
{
|
||||||
|
td0[drive].gap3_len = 0x0C; /* If we can't determine the GAP3 length, assume the smallest one we possibly know of. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (td0[drive].tracks > 43) td0[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
|
||||||
|
|
||||||
|
if(head_count == 2)
|
||||||
|
{
|
||||||
|
td0[drive].disk_flags = 8; /* 2 sides */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
td0[drive].disk_flags = 0; /* 1 side */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (td0[drive].tracks > 43) td0[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
|
||||||
|
|
||||||
|
td0[drive].sides = head_count;
|
||||||
|
|
||||||
|
td0[drive].current_side_flags[0] = td0[drive].side_flags[0][0];
|
||||||
|
td0[drive].current_side_flags[1] = td0[drive].side_flags[0][1];
|
||||||
|
|
||||||
|
pclog("TD0: File loaded: %i tracks, %i sides, disk flags: %02X, side flags %02X, %02X\n", td0[drive].tracks, td0[drive].sides, td0[drive].disk_flags, td0[drive].current_side_flags[0], td0[drive].current_side_flags[1]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void td0_seek(int drive, int track)
|
||||||
|
{
|
||||||
|
int side;
|
||||||
|
|
||||||
|
uint8_t id[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
int sector, current_pos;
|
||||||
|
|
||||||
|
int ssize = 512;
|
||||||
|
|
||||||
|
int track_rate = 0;
|
||||||
|
int track_gap3 = 12;
|
||||||
|
|
||||||
|
if (!td0[drive].f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
|
||||||
|
track /= 2;
|
||||||
|
|
||||||
|
td0[drive].track = track;
|
||||||
|
|
||||||
|
td0[drive].current_side_flags[0] = td0[drive].side_flags[track][0];
|
||||||
|
td0[drive].current_side_flags[1] = td0[drive].side_flags[track][1];
|
||||||
|
|
||||||
|
d86f_reset_index_hole_pos(drive, 0);
|
||||||
|
d86f_reset_index_hole_pos(drive, 1);
|
||||||
|
|
||||||
|
for (side = 0; side < td0[drive].sides; side++)
|
||||||
|
{
|
||||||
|
track_rate = td0[drive].current_side_flags[side] & 7;
|
||||||
|
if (!track_rate && (td0[drive].current_side_flags[side] & 0x20)) track_rate = 4;
|
||||||
|
track_gap3 = gap3_sizes[track_rate][td0[drive].sects[track][side][0].size][td0[drive].track_spt[track][side]];
|
||||||
|
|
||||||
|
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
|
||||||
|
|
||||||
|
for (sector = 0; sector < td0[drive].track_spt[track][side]; sector++)
|
||||||
|
{
|
||||||
|
id[0] = td0[drive].sects[track][side][sector].track;
|
||||||
|
id[1] = td0[drive].sects[track][side][sector].head;
|
||||||
|
id[2] = td0[drive].sects[track][side][sector].sector;
|
||||||
|
id[3] = td0[drive].sects[track][side][sector].size;
|
||||||
|
// pclog("TD0: %i %i %i %i (%i %i) (GPL=%i)\n", id[0], id[1], id[2], id[3], td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc, track_gap3);
|
||||||
|
ssize = 128 << ((uint32_t) td0[drive].sects[track][side][sector].size);
|
||||||
|
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][sector].data, ssize, 1, 0x22, track_gap3, 0, td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pclog("Seeked to track: %i (%02X, %02X)\n", td0[drive].track, td0[drive].current_side_flags[0], td0[drive].current_side_flags[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t td0_disk_flags(int drive)
|
||||||
|
{
|
||||||
|
return td0[drive].disk_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t td0_side_flags(int drive)
|
||||||
|
{
|
||||||
|
int side = 0;
|
||||||
|
side = fdd_get_head(drive);
|
||||||
|
return td0[drive].current_side_flags[side];
|
||||||
|
}
|
||||||
|
|
||||||
|
void td0_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
td0[drive].current_sector_index[side] = 0;
|
||||||
|
if (c != td0[drive].track) return;
|
||||||
|
for (i = 0; i < td0[drive].track_spt[c][side]; i++)
|
||||||
|
{
|
||||||
|
if ((td0[drive].sects[c][side][i].track == c) &&
|
||||||
|
(td0[drive].sects[c][side][i].head == h) &&
|
||||||
|
(td0[drive].sects[c][side][i].sector == r) &&
|
||||||
|
(td0[drive].sects[c][side][i].size == n))
|
||||||
|
{
|
||||||
|
td0[drive].current_sector_index[side] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t td0_poll_read_data(int drive, int side, uint16_t pos)
|
||||||
|
{
|
||||||
|
return td0[drive].sects[td0[drive].track][side][td0[drive].current_sector_index[side]].data[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
void d86f_register_td0(int drive)
|
||||||
|
{
|
||||||
|
d86f_handler[drive].disk_flags = td0_disk_flags;
|
||||||
|
d86f_handler[drive].side_flags = td0_side_flags;
|
||||||
|
d86f_handler[drive].writeback = null_writeback;
|
||||||
|
d86f_handler[drive].set_sector = td0_set_sector;
|
||||||
|
d86f_handler[drive].read_data = td0_poll_read_data;
|
||||||
|
d86f_handler[drive].write_data = null_poll_write_data;
|
||||||
|
d86f_handler[drive].format_conditions = null_format_conditions;
|
||||||
|
d86f_handler[drive].check_crc = 1;
|
||||||
|
}
|
7
src/disc_td0.h
Normal file
7
src/disc_td0.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Copyright holders: Kiririn
|
||||||
|
see COPYING for more details
|
||||||
|
*/
|
||||||
|
void td0_init();
|
||||||
|
void td0_load(int drive, char *fn);
|
||||||
|
void td0_close(int drive);
|
||||||
|
void td0_seek(int drive, int track);
|
@@ -560,7 +560,7 @@ hard_disk_t hdc[4];
|
|||||||
|
|
||||||
uint64_t hdt[128][3];
|
uint64_t hdt[128][3];
|
||||||
|
|
||||||
int image_is_hdi(char *s);
|
int image_is_hdi(const char *s);
|
||||||
|
|
||||||
/*Keyboard*/
|
/*Keyboard*/
|
||||||
int64_t keybsenddelay;
|
int64_t keybsenddelay;
|
||||||
|
70
src/ide.c
70
src/ide.c
@@ -10,6 +10,7 @@
|
|||||||
#define _LARGEFILE64_SOURCE
|
#define _LARGEFILE64_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -362,18 +363,20 @@ int cur_ide[3];
|
|||||||
|
|
||||||
uint8_t getstat(IDE *ide) { return ide->atastat; }
|
uint8_t getstat(IDE *ide) { return ide->atastat; }
|
||||||
|
|
||||||
int image_is_hdi(char *s)
|
int image_is_hdi(const char *s)
|
||||||
{
|
{
|
||||||
int len;
|
int i, len;
|
||||||
char ext[5] = { 0, 0, 0, 0, 0 };
|
char ext[5] = { 0, 0, 0, 0, 0 };
|
||||||
len = strlen(s);
|
len = strlen(s);
|
||||||
ext[0] = s[len - 4];
|
if ((len < 4) || (s[0] == '.'))
|
||||||
ext[1] = s[len - 3];
|
{
|
||||||
if ((ext[1] >= 0x61) && (ext[1] <= 0x7a)) ext[1] &= ~0x20;
|
return 0;
|
||||||
ext[2] = s[len - 2];
|
}
|
||||||
if ((ext[2] >= 0x61) && (ext[2] <= 0x7a)) ext[2] &= ~0x20;
|
memcpy(ext, s + len - 4, 4);
|
||||||
ext[3] = s[len - 1];
|
for (i = 0; i < 4; i++)
|
||||||
if ((ext[3] >= 0x61) && (ext[3] <= 0x7a)) ext[3] &= ~0x20;
|
{
|
||||||
|
ext[i] = toupper(ext[i]);
|
||||||
|
}
|
||||||
if (strcmp(ext, ".HDI") == 0)
|
if (strcmp(ext, ".HDI") == 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@@ -757,6 +760,11 @@ static void loadhd(IDE *ide, int d, const char *fn)
|
|||||||
ide->hdi = 0;
|
ide->hdi = 0;
|
||||||
if (ide->hdfile == NULL) {
|
if (ide->hdfile == NULL) {
|
||||||
/* Try to open existing hard disk image */
|
/* Try to open existing hard disk image */
|
||||||
|
if (fn[0] == '.')
|
||||||
|
{
|
||||||
|
ide->type = IDE_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
ide->hdfile = fopen64(fn, "rb+");
|
ide->hdfile = fopen64(fn, "rb+");
|
||||||
if (ide->hdfile == NULL) {
|
if (ide->hdfile == NULL) {
|
||||||
/* Failed to open existing hard disk image */
|
/* Failed to open existing hard disk image */
|
||||||
@@ -800,34 +808,34 @@ static void loadhd(IDE *ide, int d, const char *fn)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
if (image_is_hdi(fn))
|
|
||||||
{
|
{
|
||||||
fseek(ide->hdfile, 0x8, SEEK_SET);
|
if (image_is_hdi(fn))
|
||||||
fread(&(ide->base), 1, 4, ide->hdfile);
|
|
||||||
fseek(ide->hdfile, 0x10, SEEK_SET);
|
|
||||||
fread(§or_size, 1, 4, ide->hdfile);
|
|
||||||
if (sector_size != 512)
|
|
||||||
{
|
{
|
||||||
/* Sector size is not 512 */
|
fseek(ide->hdfile, 0x8, SEEK_SET);
|
||||||
fclose(ide->hdfile);
|
fread(&(ide->base), 1, 4, ide->hdfile);
|
||||||
ide->type = IDE_NONE;
|
fseek(ide->hdfile, 0x10, SEEK_SET);
|
||||||
return;
|
fread(§or_size, 1, 4, ide->hdfile);
|
||||||
|
if (sector_size != 512)
|
||||||
|
{
|
||||||
|
/* Sector size is not 512 */
|
||||||
|
fclose(ide->hdfile);
|
||||||
|
ide->type = IDE_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fread(&(hdc[d].spt), 1, 4, ide->hdfile);
|
||||||
|
fread(&(hdc[d].hpc), 1, 4, ide->hdfile);
|
||||||
|
fread(&(hdc[d].tracks), 1, 4, ide->hdfile);
|
||||||
|
ide->hdi = 1;
|
||||||
}
|
}
|
||||||
fread(&(hdc[d].spt), 1, 4, ide->hdfile);
|
|
||||||
fread(&(hdc[d].hpc), 1, 4, ide->hdfile);
|
|
||||||
fread(&(hdc[d].tracks), 1, 4, ide->hdfile);
|
|
||||||
ide->hdi = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ide->spt = hdc[d].spt;
|
ide->spt = hdc[d].spt;
|
||||||
ide->hpc = hdc[d].hpc;
|
ide->hpc = hdc[d].hpc;
|
||||||
ide->tracks = hdc[d].tracks;
|
ide->tracks = hdc[d].tracks;
|
||||||
ide->type = IDE_HDD;
|
ide->type = IDE_HDD;
|
||||||
ide->hdc_num = d;
|
ide->hdc_num = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ide_set_signature(IDE *ide)
|
void ide_set_signature(IDE *ide)
|
||||||
|
@@ -542,8 +542,9 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc0: /*Read input port*/
|
case 0xc0: /*Read input port*/
|
||||||
keyboard_at_adddata(keyboard_at.input_port | 4);
|
keyboard_at_adddata((keyboard_at.input_port & 0xf0) | 0x80);
|
||||||
keyboard_at.input_port = ((keyboard_at.input_port + 1) & 3) | (keyboard_at.input_port & 0xfc);
|
// keyboard_at_adddata(keyboard_at.input_port | 4);
|
||||||
|
// keyboard_at.input_port = ((keyboard_at.input_port + 1) & 3) | (keyboard_at.input_port & 0xfc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc9: /*AMI - block P22 and P23 ??? */
|
case 0xc9: /*AMI - block P22 and P23 ??? */
|
||||||
|
@@ -1001,7 +1001,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||||||
break;
|
break;
|
||||||
case IDM_DISC_A:
|
case IDM_DISC_A:
|
||||||
case IDM_DISC_A_WP:
|
case IDM_DISC_A_WP:
|
||||||
if (!getfile(hwnd,"Disc image (*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.XDF;*.VFD)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.XDF;*.VFD\0All files (*.*)\0*.*\0",discfns[0]))
|
if (!getfile(hwnd,"Disc image (*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF\0All files (*.*)\0*.*\0",discfns[0]))
|
||||||
{
|
{
|
||||||
disc_close(0);
|
disc_close(0);
|
||||||
ui_writeprot[0] = (LOWORD(wParam) == IDM_DISC_A_WP) ? 1 : 0;
|
ui_writeprot[0] = (LOWORD(wParam) == IDM_DISC_A_WP) ? 1 : 0;
|
||||||
@@ -1011,7 +1011,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||||||
break;
|
break;
|
||||||
case IDM_DISC_B:
|
case IDM_DISC_B:
|
||||||
case IDM_DISC_B_WP:
|
case IDM_DISC_B_WP:
|
||||||
if (!getfile(hwnd,"Disc image (*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.XDF;*.VFD)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.XDF;*.VFD\0All files (*.*)\0*.*\0",discfns[1]))
|
if (!getfile(hwnd,"Disc image (*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF\0All files (*.*)\0*.*\0",discfns[1]))
|
||||||
{
|
{
|
||||||
disc_close(1);
|
disc_close(1);
|
||||||
ui_writeprot[1] = (LOWORD(wParam) == IDM_DISC_B_WP) ? 1 : 0;
|
ui_writeprot[1] = (LOWORD(wParam) == IDM_DISC_B_WP) ? 1 : 0;
|
||||||
|
Reference in New Issue
Block a user