Skip to content

Commit 060f769

Browse files
committed
Merge branch 'karlvr-fdd-write'
2 parents 92e79dd + aba4878 commit 060f769

File tree

4 files changed

+73
-8
lines changed

4 files changed

+73
-8
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
## What's New
22

3+
* **11-Jan-2024**: writing data back to floppy is now supported in the CPC emulation
4+
(see: https://github.com/floooh/chips/issues/104 and https://github.com/floooh/chips/pull/105),
5+
note though that the floppy emulation in the CPC is still very rough.
6+
7+
Many thanks to @karlvr for the PR!
8+
39
* **02-Jan-2024**: Integrated some 'structural ideas' from the Zig Z80 emulator into z80.h
410
(everything backward compatible and no behaviour changes):
511
- Got rid of lookup tables which mapped opcodes to the first instruction

chips/fdd.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ int fdd_seek_track(fdd_t* fdd, int track);
125125
int fdd_seek_sector(fdd_t* fdd, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n);
126126
// read the next byte from the seeked-to sector, return FDD_RESULT_*
127127
int fdd_read(fdd_t* fdd, int side, uint8_t* out_data);
128+
// write the next byte to the seeked-to sector, return FDD_RESULT_*
129+
int fdd_write(fdd_t* fdd, int side, uint8_t data);
128130

129131
#ifdef __cplusplus
130132
} /* extern "C" */
@@ -292,4 +294,25 @@ int fdd_read(fdd_t* fdd, int side, uint8_t* out_data) {
292294
return FDD_RESULT_NOT_READY;
293295
}
294296

297+
int fdd_write(fdd_t* fdd, int side, uint8_t data) {
298+
CHIPS_ASSERT(fdd && (side >= 0) && (side < FDD_MAX_SIDES));
299+
if (fdd->has_disc & fdd->motor_on) {
300+
fdd->cur_side = side;
301+
const fdd_sector_t* sector = &fdd->disc.tracks[side][fdd->cur_track_index].sectors[fdd->cur_sector_index];
302+
if (fdd->cur_sector_pos < sector->data_size) {
303+
const int data_offset = sector->data_offset + fdd->cur_sector_pos;
304+
fdd->data[data_offset] = data;
305+
fdd->cur_sector_pos++;
306+
if (fdd->cur_sector_pos < sector->data_size) {
307+
return FDD_RESULT_SUCCESS;
308+
}
309+
else {
310+
return FDD_RESULT_END_OF_SECTOR;
311+
}
312+
}
313+
return FDD_RESULT_NOT_FOUND;
314+
}
315+
return FDD_RESULT_NOT_READY;
316+
}
317+
295318
#endif /* CHIPS_IMPL */

chips/upd765.h

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ typedef int (*upd765_seektrack_cb)(int drive, int track, void* user_data);
209209
typedef int (*upd765_seeksector_cb)(int drive, int side, upd765_sectorinfo_t* inout_info, void* user_data);
210210
/* callback to read the next sector data byte */
211211
typedef int (*upd765_read_cb)(int drive, int side, void* user_data, uint8_t* out_data);
212+
/* callback to write the next sector data byte */
213+
typedef int (*upd765_write_cb)(int drive, int side, void* user_data, uint8_t data);
212214
/* callback to read info about first sector on current reack */
213215
typedef int (*upd765_trackinfo_cb)(int drive, int side, void* user_data, upd765_sectorinfo_t* out_info);
214216
/* callback to get info about disk drive (called on SENSE_DRIVE_STATUS command) */
@@ -219,6 +221,7 @@ typedef struct {
219221
upd765_seektrack_cb seektrack_cb;
220222
upd765_seeksector_cb seeksector_cb;
221223
upd765_read_cb read_cb;
224+
upd765_write_cb write_cb;
222225
upd765_trackinfo_cb trackinfo_cb;
223226
upd765_driveinfo_cb driveinfo_cb;
224227
void* user_data;
@@ -242,6 +245,7 @@ typedef struct {
242245
upd765_seektrack_cb seektrack_cb;
243246
upd765_seeksector_cb seeksector_cb;
244247
upd765_read_cb read_cb;
248+
upd765_write_cb write_cb;
245249
upd765_trackinfo_cb trackinfo_cb;
246250
upd765_driveinfo_cb driveinfo_cb;
247251
void* user_data;
@@ -394,6 +398,7 @@ static void _upd765_cmd(upd765_t* upd) {
394398
CHIPS_ASSERT(upd->phase == UPD765_PHASE_COMMAND);
395399
switch (upd->cmd) {
396400
case UPD765_CMD_READ_DATA:
401+
case UPD765_CMD_WRITE_DATA:
397402
{
398403
upd->st[0] = upd->fifo[1] & 7; /* HD, US1, US0 */
399404
upd->sector_info.c = upd->fifo[2];
@@ -528,7 +533,6 @@ static void _upd765_cmd(upd765_t* upd) {
528533
break;
529534

530535
case UPD765_CMD_READ_DELETED_DATA:
531-
case UPD765_CMD_WRITE_DATA:
532536
case UPD765_CMD_WRITE_DELETED_DATA:
533537
case UPD765_CMD_READ_A_TRACK:
534538
case UPD765_CMD_FORMAT_A_TRACK:
@@ -575,9 +579,27 @@ static uint8_t _upd765_exec_rd(upd765_t* upd) {
575579

576580
/* called when a byte is written during the exec phase */
577581
static void _upd765_exec_wr(upd765_t* upd, uint8_t data) {
578-
// FIXME
579-
(void)upd;
580-
(void)data;
582+
CHIPS_ASSERT(upd->phase == UPD765_PHASE_EXEC);
583+
switch (upd->cmd) {
584+
case UPD765_CMD_WRITE_DATA:
585+
{
586+
/* write next sector data byte to FDD */
587+
const int fdd_index = upd->st[0] & 3;
588+
const int side = (upd->st[0] & 4) >> 2;
589+
const int res = upd->write_cb(fdd_index, side, upd->user_data, data);
590+
if (res != UPD765_RESULT_SUCCESS) {
591+
if (res & UPD765_RESULT_NOT_READY) {
592+
upd->st[0] |= UPD765_ST0_NR;
593+
}
594+
_upd765_to_phase_result(upd);
595+
}
596+
}
597+
break;
598+
default:
599+
/* shouldn't happen */
600+
CHIPS_ASSERT(false);
601+
break;
602+
}
581603
}
582604

583605
/* write a data byte to the upd765 */
@@ -627,9 +649,6 @@ static inline uint8_t _upd765_read_status(upd765_t* upd) {
627649
for between 2us and 50us, for now just indicate
628650
that we're always ready during the command and result phase
629651
*/
630-
/* FIXME: data direction is currently always set as FDC->CPU,
631-
since the emulation doesn't support write operations
632-
*/
633652
switch (upd->phase) {
634653
case UPD765_PHASE_IDLE:
635654
status |= UPD765_STATUS_RQM;
@@ -638,7 +657,12 @@ static inline uint8_t _upd765_read_status(upd765_t* upd) {
638657
status |= UPD765_STATUS_CB|UPD765_STATUS_RQM;
639658
break;
640659
case UPD765_PHASE_EXEC:
641-
status |= UPD765_STATUS_CB|UPD765_STATUS_EXM|UPD765_STATUS_DIO|UPD765_STATUS_RQM;
660+
status |= UPD765_STATUS_CB|UPD765_STATUS_EXM|UPD765_STATUS_RQM;
661+
// NOTE: the DIO bit is associated with fifo_write and internal_drq
662+
// booleans in MAME, so it's a bit more complicated than what we do here
663+
if (upd->cmd != UPD765_CMD_WRITE_DATA) {
664+
status |= UPD765_STATUS_DIO;
665+
}
642666
break;
643667
case UPD765_PHASE_RESULT:
644668
status |= UPD765_STATUS_CB|UPD765_STATUS_DIO|UPD765_STATUS_RQM;
@@ -658,6 +682,7 @@ void upd765_init(upd765_t* upd, const upd765_desc_t* desc) {
658682
upd->seektrack_cb = desc->seektrack_cb;
659683
upd->seeksector_cb = desc->seeksector_cb;
660684
upd->read_cb = desc->read_cb;
685+
upd->write_cb = desc->write_cb;
661686
upd->trackinfo_cb = desc->trackinfo_cb;
662687
upd->driveinfo_cb = desc->driveinfo_cb;
663688
upd->user_data = desc->user_data;

systems/cpc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ static void _cpc_bankswitch(uint8_t ram_config, uint8_t rom_enable, uint8_t rom_
234234
static int _cpc_fdc_seektrack(int drive, int track, void* user_data);
235235
static int _cpc_fdc_seeksector(int drive, int side, upd765_sectorinfo_t* inout_info, void* user_data);
236236
static int _cpc_fdc_read(int drive, int side, void* user_data, uint8_t* out_data);
237+
static int _cpc_fdc_write(int drive, int side, void* user_data, uint8_t data);
237238
static int _cpc_fdc_trackinfo(int drive, int side, void* user_data, upd765_sectorinfo_t* out_info);
238239
static void _cpc_fdc_driveinfo(int drive, void* user_data, upd765_driveinfo_t* out_info);
239240

@@ -302,6 +303,7 @@ void cpc_init(cpc_t* sys, const cpc_desc_t* desc) {
302303
.seektrack_cb = _cpc_fdc_seektrack,
303304
.seeksector_cb = _cpc_fdc_seeksector,
304305
.read_cb = _cpc_fdc_read,
306+
.write_cb = _cpc_fdc_write,
305307
.trackinfo_cb = _cpc_fdc_trackinfo,
306308
.driveinfo_cb = _cpc_fdc_driveinfo,
307309
.user_data = sys,
@@ -984,6 +986,15 @@ static int _cpc_fdc_read(int drive, int side, void* user_data, uint8_t* out_data
984986
}
985987
}
986988

989+
static int _cpc_fdc_write(int drive, int side, void* user_data, uint8_t data) {
990+
if (0 == drive) {
991+
cpc_t* sys = (cpc_t*) user_data;
992+
return fdd_write(&sys->fdd, side, data);
993+
} else {
994+
return UPD765_RESULT_NOT_READY;
995+
}
996+
}
997+
987998
static int _cpc_fdc_trackinfo(int drive, int side, void* user_data, upd765_sectorinfo_t* out_info) {
988999
CHIPS_ASSERT((side >= 0) && (side < 2));
9891000
if (0 == drive) {

0 commit comments

Comments
 (0)