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:
parent
2dd21f1487
commit
a6c1564747
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user