1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-11-27 05:49:24 +00:00

Add fwrite function, support for streams and types

This commit is contained in:
Peter Evans 2018-02-03 20:50:08 -06:00
parent 2dd21f1487
commit a6c1564747
5 changed files with 92 additions and 6 deletions

View File

@ -140,6 +140,12 @@ struct apple2dd {
vm_segment *image; vm_segment *image;
int image_type; int image_type;
/*
* This is the means by which we can save the image data back to the
* origin stream, if possible.
*/
FILE *stream;
/* /*
* A disk drive may be "off" or "on", regardless of whether it's * A disk drive may be "off" or "on", regardless of whether it's
* been selected by the peripheral interface. * been selected by the peripheral interface.
@ -182,7 +188,10 @@ extern apple2dd *apple2_dd_create();
extern int apple2_dd_insert(apple2dd *, FILE *, int); extern int apple2_dd_insert(apple2dd *, FILE *, int);
extern int apple2_dd_position(apple2dd *); extern int apple2_dd_position(apple2dd *);
extern vm_8bit apple2_dd_read(apple2dd *); extern vm_8bit apple2_dd_read(apple2dd *);
extern vm_8bit apple2_dd_switch_rw(apple2dd *);
extern void apple2_dd_eject(apple2dd *); extern void apple2_dd_eject(apple2dd *);
extern void apple2_dd_encode(apple2dd *);
extern void apple2_dd_decode(apple2dd *);
extern void apple2_dd_free(apple2dd *); extern void apple2_dd_free(apple2dd *);
extern void apple2_dd_map(vm_segment *); extern void apple2_dd_map(vm_segment *);
extern void apple2_dd_set_mode(apple2dd *, int); extern void apple2_dd_set_mode(apple2dd *, int);
@ -191,7 +200,6 @@ extern void apple2_dd_step(apple2dd *, int);
extern void apple2_dd_switch_drive(apple2 *, size_t); extern void apple2_dd_switch_drive(apple2 *, size_t);
extern void apple2_dd_switch_latch(apple2dd *, vm_8bit); extern void apple2_dd_switch_latch(apple2dd *, vm_8bit);
extern void apple2_dd_switch_phase(apple2dd *, size_t); extern void apple2_dd_switch_phase(apple2dd *, size_t);
extern vm_8bit apple2_dd_switch_rw(apple2dd *);
extern void apple2_dd_turn_on(apple2dd *, bool); extern void apple2_dd_turn_on(apple2dd *, bool);
extern void apple2_dd_write(apple2dd *); extern void apple2_dd_write(apple2dd *);
extern void apple2_dd_write_protect(apple2dd *, bool); extern void apple2_dd_write_protect(apple2dd *, bool);

View File

@ -64,5 +64,6 @@ extern int apple2_enc_sector(vm_segment *, vm_segment *, int, int);
extern int apple2_enc_sector_header(vm_segment *, int, int, int); extern int apple2_enc_sector_header(vm_segment *, int, int, int);
extern int apple2_enc_track(vm_segment *, vm_segment *, int, int); extern int apple2_enc_track(vm_segment *, vm_segment *, int, int);
extern vm_segment *apple2_enc_dos(vm_segment *); extern vm_segment *apple2_enc_dos(vm_segment *);
extern vm_segment *apple2_enc_nib(vm_segment *);
#endif #endif

View File

@ -62,6 +62,7 @@ struct vm_segment {
extern int vm_segment_copy(vm_segment *, vm_segment *, size_t, size_t, size_t); extern int vm_segment_copy(vm_segment *, vm_segment *, size_t, size_t, size_t);
extern int vm_segment_copy_buf(vm_segment *, const vm_8bit *, size_t, size_t, size_t); extern int vm_segment_copy_buf(vm_segment *, const vm_8bit *, size_t, size_t, size_t);
extern int vm_segment_fread(vm_segment *, FILE *, size_t, size_t); extern int vm_segment_fread(vm_segment *, FILE *, size_t, size_t);
extern int vm_segment_fwrite(vm_segment *, FILE *, size_t, size_t);
extern int vm_segment_read_map(vm_segment *, size_t, vm_segment_read_fn); extern int vm_segment_read_map(vm_segment *, size_t, vm_segment_read_fn);
extern int vm_segment_set(vm_segment *, size_t, vm_8bit); extern int vm_segment_set(vm_segment *, size_t, vm_8bit);
extern int vm_segment_set16(vm_segment *, size_t, vm_16bit); extern int vm_segment_set16(vm_segment *, size_t, vm_16bit);

View File

@ -2,8 +2,10 @@
* apple2.disk_drive.c * apple2.disk_drive.c
*/ */
#include "apple2.h"
#include "apple2.dd.h" #include "apple2.dd.h"
#include "apple2.dec.h"
#include "apple2.enc.h"
#include "apple2.h"
/* /*
* Create a new disk drive. We do not create a memory segment for the * Create a new disk drive. We do not create a memory segment for the
@ -70,21 +72,77 @@ apple2_dd_insert(apple2dd *drive, FILE *stream, int type)
// If we have any data, get rid of it. We'll start fresh here. // If we have any data, get rid of it. We'll start fresh here.
apple2_dd_eject(drive); apple2_dd_eject(drive);
drive->data = vm_segment_create(finfo.st_size); drive->image = vm_segment_create(finfo.st_size);
drive->track_pos = 0; drive->track_pos = 0;
drive->sector_pos = 0; drive->sector_pos = 0;
// Read the data from the stream and write into the memory segment // Read the data from the stream and write into the memory segment
err = vm_segment_fread(drive->data, stream, 0, finfo.st_size); err = vm_segment_fread(drive->image, stream, 0, finfo.st_size);
if (err != OK) { if (err != OK) {
log_critical("Could not read data into disk drive"); log_critical("Could not read data into disk drive");
return err; return err;
} }
drive->stream = stream;
drive->image_type = type; drive->image_type = type;
// Now we need to build the data segment
apple2_dd_encode(drive);
return OK; return OK;
} }
void
apple2_dd_encode(apple2dd *drive)
{
switch (drive->image_type) {
case DD_NIBBLE:
drive->data = apple2_enc_nib(drive->image);
break;
case DD_DOS33:
case DD_PRODOS:
drive->data = apple2_enc_dos(drive->image);
break;
default:
log_critical("Unknown image type");
exit(1);
}
}
void
apple2_dd_save(apple2dd *drive)
{
// First bring the image segment back into sync with with the data
// segment.
apple2_dd_decode(drive);
if (drive->stream) {
rewind(drive->stream);
vm_segment_fwrite(drive->image, drive->stream, 0, drive->image->size);
}
}
void
apple2_dd_decode(apple2dd *drive)
{
switch (drive->image_type) {
case DD_NIBBLE:
apple2_dec_nib(drive->image, drive->data);
break;
case DD_DOS33:
case DD_PRODOS:
apple2_dec_dos(drive->image, drive->data);
break;
default:
log_critical("Unknown image type");
exit(1);
}
}
/* /*
* Evaluate the value of the phase_state against the last known phase, * Evaluate the value of the phase_state against the last known phase,
* and decide from there whether we should step forward or backward by a * and decide from there whether we should step forward or backward by a
@ -177,8 +235,13 @@ void
apple2_dd_eject(apple2dd *drive) apple2_dd_eject(apple2dd *drive)
{ {
if (drive->data) { if (drive->data) {
// Save off anything else we have left
apple2_dd_save(drive);
vm_segment_free(drive->data); vm_segment_free(drive->data);
vm_segment_free(drive->image);
drive->data = NULL; drive->data = NULL;
drive->image = NULL;
} }
drive->track_pos = 0; drive->track_pos = 0;

View File

@ -176,7 +176,7 @@ vm_segment_copy(vm_segment *dest,
size_t src_index, size_t src_index,
size_t length) size_t length)
{ {
if (src_index + length >= src->size) { if (src_index + length > src->size) {
log_critical( log_critical(
"Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)", "Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)",
src_index, src_index,
@ -186,7 +186,7 @@ vm_segment_copy(vm_segment *dest,
return ERR_OOB; return ERR_OOB;
} }
if (dest_index + length >= dest->size) { if (dest_index + length > dest->size) {
log_critical( log_critical(
"Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)", "Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)",
dest_index, dest_index,
@ -286,6 +286,19 @@ vm_segment_fread(vm_segment *segment, FILE *stream, size_t offset, size_t len)
return OK; return OK;
} }
int
vm_segment_fwrite(vm_segment *seg, FILE *stream, size_t off, size_t len)
{
fwrite(seg->memory + off, sizeof(vm_8bit), len, stream);
if (ferror(stream)) {
log_critical("Could not write to the file stream: %s", strerror(errno));
return ERR_BADFILE;
}
return OK;
}
/* /*
* Change the internal notion of the machine used by map functions * Change the internal notion of the machine used by map functions
*/ */