mirror of
https://github.com/pevans/erc-c.git
synced 2024-08-19 17:29:34 +00:00
Add fwrite function, support for streams and types
This commit is contained in:
parent
2dd21f1487
commit
a6c1564747
@ -140,6 +140,12 @@ struct apple2dd {
|
||||
vm_segment *image;
|
||||
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
|
||||
* 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_position(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_encode(apple2dd *);
|
||||
extern void apple2_dd_decode(apple2dd *);
|
||||
extern void apple2_dd_free(apple2dd *);
|
||||
extern void apple2_dd_map(vm_segment *);
|
||||
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_latch(apple2dd *, vm_8bit);
|
||||
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_write(apple2dd *);
|
||||
extern void apple2_dd_write_protect(apple2dd *, bool);
|
||||
|
@ -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_track(vm_segment *, vm_segment *, int, int);
|
||||
extern vm_segment *apple2_enc_dos(vm_segment *);
|
||||
extern vm_segment *apple2_enc_nib(vm_segment *);
|
||||
|
||||
#endif
|
||||
|
@ -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_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_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_set(vm_segment *, size_t, vm_8bit);
|
||||
extern int vm_segment_set16(vm_segment *, size_t, vm_16bit);
|
||||
|
@ -2,8 +2,10 @@
|
||||
* apple2.disk_drive.c
|
||||
*/
|
||||
|
||||
#include "apple2.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
|
||||
@ -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.
|
||||
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->sector_pos = 0;
|
||||
|
||||
// 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) {
|
||||
log_critical("Could not read data into disk drive");
|
||||
return err;
|
||||
}
|
||||
|
||||
drive->stream = stream;
|
||||
drive->image_type = type;
|
||||
|
||||
// Now we need to build the data segment
|
||||
apple2_dd_encode(drive);
|
||||
|
||||
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,
|
||||
* and decide from there whether we should step forward or backward by a
|
||||
@ -177,8 +235,13 @@ void
|
||||
apple2_dd_eject(apple2dd *drive)
|
||||
{
|
||||
if (drive->data) {
|
||||
// Save off anything else we have left
|
||||
apple2_dd_save(drive);
|
||||
|
||||
vm_segment_free(drive->data);
|
||||
vm_segment_free(drive->image);
|
||||
drive->data = NULL;
|
||||
drive->image = NULL;
|
||||
}
|
||||
|
||||
drive->track_pos = 0;
|
||||
|
@ -176,7 +176,7 @@ vm_segment_copy(vm_segment *dest,
|
||||
size_t src_index,
|
||||
size_t length)
|
||||
{
|
||||
if (src_index + length >= src->size) {
|
||||
if (src_index + length > src->size) {
|
||||
log_critical(
|
||||
"Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)",
|
||||
src_index,
|
||||
@ -186,7 +186,7 @@ vm_segment_copy(vm_segment *dest,
|
||||
return ERR_OOB;
|
||||
}
|
||||
|
||||
if (dest_index + length >= dest->size) {
|
||||
if (dest_index + length > dest->size) {
|
||||
log_critical(
|
||||
"Attempt to copy beyond bounds of vm_segment (%d + %d >= %d)",
|
||||
dest_index,
|
||||
@ -286,6 +286,19 @@ vm_segment_fread(vm_segment *segment, FILE *stream, size_t offset, size_t len)
|
||||
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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user