mirror of
https://github.com/libretro/frodo-libretro.git
synced 2026-11-07 10:36:03 -10:00
Start using VFS/filestream functions
This commit is contained in:
1 parent
009e5a779b
commit
770313ba24
12 files changed
+1611
-1584
No files matched your search
@@ -21,6 +21,8 @@ SOURCES_C := \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/trans_stream_zlib.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/file_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path_io.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path.c \
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c
|
||||
|
||||
+1068
-931
File diff suppressed because it is too large.
Load diff
+6
-4
@@ -24,6 +24,8 @@
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
#include <streams/file_stream.h>
|
||||
|
||||
#include "IEC.h"
|
||||
|
||||
/*
|
||||
@@ -123,7 +125,7 @@ private:
|
||||
virtual void new_cmd(const uint8 *name, int name_len, const uint8 *comma);
|
||||
virtual void validate_cmd(void);
|
||||
|
||||
FILE *the_file; // File pointer for image file
|
||||
RFILE *the_file; // File pointer for image file
|
||||
image_file_desc desc; // Image file descriptor
|
||||
bool write_protected; // Flag: image file write-protected
|
||||
|
||||
@@ -143,12 +145,12 @@ private:
|
||||
|
||||
// Check whether file with given header (64 bytes) and size looks like one
|
||||
// of the file types supported by this module
|
||||
extern bool IsImageFile(const char *path, const uint8 *header, long size);
|
||||
bool IsImageFile(const char *path, const uint8 *header, int64_t size);
|
||||
|
||||
// Read directory of disk image file into (empty) c64_dir_entry vector
|
||||
extern bool ReadImageDirectory(const char *path, std::vector<c64_dir_entry> &vec);
|
||||
bool ReadImageDirectory(const char *path, std::vector<c64_dir_entry> &vec);
|
||||
|
||||
// Create new blank disk image file
|
||||
extern bool CreateImageFile(const char *path);
|
||||
bool CreateImageFile(const char *path);
|
||||
|
||||
#endif
|
||||
+138
-133
@@ -45,24 +45,23 @@
|
||||
#include "CPU1541.h"
|
||||
#include "Prefs.h"
|
||||
|
||||
/* Number of tracks/sectors */
|
||||
#define NUM_TRACKS 35
|
||||
#define NUM_SECTORS 683
|
||||
|
||||
// Number of tracks/sectors
|
||||
const int NUM_TRACKS = 35;
|
||||
const int NUM_SECTORS = 683;
|
||||
|
||||
// Size of GCR encoded data
|
||||
/* Size of GCR encoded data */
|
||||
const int GCR_SECTOR_SIZE = 1+10+9+1+325+8; // SYNC Header Gap SYNC Data Gap (should be 5 SYNC bytes each)
|
||||
const int GCR_TRACK_SIZE = GCR_SECTOR_SIZE * 21; // Each track in gcr_data has 21 sectors
|
||||
const int GCR_DISK_SIZE = GCR_TRACK_SIZE * NUM_TRACKS;
|
||||
const int GCR_TRACK_SIZE = GCR_SECTOR_SIZE * 21; // Each track in gcr_data has 21 sectors
|
||||
const int GCR_DISK_SIZE = GCR_TRACK_SIZE * NUM_TRACKS;
|
||||
|
||||
// Job return codes
|
||||
const int RET_OK = 1; // No error
|
||||
const int RET_NOT_FOUND = 2; // Block not found
|
||||
const int RET_NOT_READY = 15; // Drive not ready
|
||||
/* Job return codes */
|
||||
#define RET_OK 1 /* No error */
|
||||
#define RET_NOT_FOUND 2 /* Block not found */
|
||||
#define RET_NOT_READY 15 /* Drive not ready */
|
||||
|
||||
|
||||
// Number of sectors of each track
|
||||
const int num_sectors[36] = {
|
||||
/* Number of sectors of each track */
|
||||
const int num_sectors[36] =
|
||||
{
|
||||
0,
|
||||
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
|
||||
19,19,19,19,19,19,19,
|
||||
@@ -71,14 +70,26 @@ const int num_sectors[36] = {
|
||||
};
|
||||
|
||||
// Sector offset of start of track in .d64 file
|
||||
const int sector_offset[36] = {
|
||||
0,
|
||||
0,21,42,63,84,105,126,147,168,189,210,231,252,273,294,315,336,
|
||||
357,376,395,414,433,452,471,
|
||||
490,508,526,544,562,580,
|
||||
598,615,632,649,666
|
||||
const int sector_offset[36] =
|
||||
{
|
||||
0,
|
||||
0,21,42,63,84,105,126,147,168,189,210,231,252,273,294,315,336,
|
||||
357,376,395,414,433,452,471,
|
||||
490,508,526,544,562,580,
|
||||
598,615,632,649,666
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
extern "C" {
|
||||
RFILE* rfopen(const char *path, const char *mode);
|
||||
int64_t rfseek(RFILE* stream, int64_t offset, int origin);
|
||||
int64_t rftell(RFILE* stream);
|
||||
int rfclose(RFILE* stream);
|
||||
int64_t rfread(void* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream);
|
||||
int64_t rfwrite(void const* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor: Open .d64 file if processor-level 1541
|
||||
@@ -87,13 +98,13 @@ const int sector_offset[36] = {
|
||||
|
||||
Job1541::Job1541(uint8 *ram1541) : ram(ram1541)
|
||||
{
|
||||
the_file = NULL;
|
||||
the_file = NULL;
|
||||
|
||||
gcr_data = gcr_ptr = gcr_track_start = new uint8[GCR_DISK_SIZE];
|
||||
gcr_track_end = gcr_track_start + GCR_TRACK_SIZE;
|
||||
gcr_data = gcr_ptr = gcr_track_start = new uint8[GCR_DISK_SIZE];
|
||||
gcr_track_end = gcr_track_start + GCR_TRACK_SIZE;
|
||||
current_halftrack = 2;
|
||||
|
||||
disk_changed = true;
|
||||
disk_changed = true;
|
||||
|
||||
if (ThePrefs.Emul1541Proc)
|
||||
open_d64_file(ThePrefs.DrivePath[0]);
|
||||
@@ -111,10 +122,7 @@ Job1541::~Job1541()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Preferences may have changed
|
||||
*/
|
||||
|
||||
/* Preferences may have changed */
|
||||
void Job1541::NewPrefs(Prefs *prefs)
|
||||
{
|
||||
// 1541 emulation turned off?
|
||||
@@ -126,69 +134,74 @@ void Job1541::NewPrefs(Prefs *prefs)
|
||||
open_d64_file(prefs->DrivePath[0]);
|
||||
|
||||
// .d64 file name changed?
|
||||
else if (strcmp(ThePrefs.DrivePath[0], prefs->DrivePath[0])) {
|
||||
close_d64_file();
|
||||
open_d64_file(prefs->DrivePath[0]);
|
||||
disk_changed = true;
|
||||
}
|
||||
else if (strcmp(ThePrefs.DrivePath[0], prefs->DrivePath[0]))
|
||||
{
|
||||
close_d64_file();
|
||||
open_d64_file(prefs->DrivePath[0]);
|
||||
disk_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open .d64 file
|
||||
*/
|
||||
|
||||
/* Open .d64 file */
|
||||
void Job1541::open_d64_file(char *filepath)
|
||||
{
|
||||
long size;
|
||||
uint8 magic[4];
|
||||
uint8 bam[256];
|
||||
|
||||
// Clear GCR buffer
|
||||
/* Clear GCR buffer */
|
||||
memset(gcr_data, 0x55, GCR_DISK_SIZE);
|
||||
|
||||
// Try opening the file for reading/writing first, then for reading only
|
||||
/* Try opening the file for reading/writing first,
|
||||
then for reading only */
|
||||
write_protected = false;
|
||||
the_file = fopen(filepath, "rb+");
|
||||
if (the_file == NULL) {
|
||||
write_protected = true;
|
||||
the_file = fopen(filepath, "rb");
|
||||
}
|
||||
if (the_file != NULL) {
|
||||
the_file = rfopen(filepath, "rb+");
|
||||
if (!the_file)
|
||||
{
|
||||
write_protected = true;
|
||||
the_file = rfopen(filepath, "rb");
|
||||
}
|
||||
if (the_file)
|
||||
{
|
||||
// Check length
|
||||
rfseek(the_file, 0, SEEK_END);
|
||||
if ((size = rftell(the_file)) < NUM_SECTORS * 256)
|
||||
{
|
||||
rfclose(the_file);
|
||||
the_file = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check length
|
||||
fseek(the_file, 0, SEEK_END);
|
||||
if ((size = ftell(the_file)) < NUM_SECTORS * 256) {
|
||||
fclose(the_file);
|
||||
the_file = NULL;
|
||||
return;
|
||||
}
|
||||
// x64 image?
|
||||
rfseek(the_file, 0, SEEK_SET);
|
||||
rfread(&magic, 4, 1, the_file);
|
||||
if ( magic[0] == 0x43
|
||||
&& magic[1] == 0x15
|
||||
&& magic[2] == 0x41
|
||||
&& magic[3] == 0x64)
|
||||
image_header = 64;
|
||||
else
|
||||
image_header = 0;
|
||||
|
||||
// x64 image?
|
||||
fseek(the_file, 0, SEEK_SET);
|
||||
fread(&magic, 4, 1, the_file);
|
||||
if (magic[0] == 0x43 && magic[1] == 0x15 && magic[2] == 0x41 && magic[3] == 0x64)
|
||||
image_header = 64;
|
||||
else
|
||||
image_header = 0;
|
||||
// Preset error info (all sectors no error)
|
||||
memset(error_info, 1, NUM_SECTORS);
|
||||
|
||||
// Preset error info (all sectors no error)
|
||||
memset(error_info, 1, NUM_SECTORS);
|
||||
// Load sector error info from .d64 file, if present
|
||||
if (!image_header && size == NUM_SECTORS * 257)
|
||||
{
|
||||
rfseek(the_file, NUM_SECTORS * 256, SEEK_SET);
|
||||
rfread(&error_info, NUM_SECTORS, 1, the_file);
|
||||
}
|
||||
|
||||
// Load sector error info from .d64 file, if present
|
||||
if (!image_header && size == NUM_SECTORS * 257) {
|
||||
fseek(the_file, NUM_SECTORS * 256, SEEK_SET);
|
||||
fread(&error_info, NUM_SECTORS, 1, the_file);
|
||||
};
|
||||
// Read BAM and get ID
|
||||
read_sector(18, 0, bam);
|
||||
id1 = bam[162];
|
||||
id2 = bam[163];
|
||||
|
||||
// Read BAM and get ID
|
||||
read_sector(18, 0, bam);
|
||||
id1 = bam[162];
|
||||
id2 = bam[163];
|
||||
|
||||
// Create GCR encoded disk data from image
|
||||
disk2gcr();
|
||||
}
|
||||
// Create GCR encoded disk data from image
|
||||
disk2gcr();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,10 +211,10 @@ void Job1541::open_d64_file(char *filepath)
|
||||
|
||||
void Job1541::close_d64_file(void)
|
||||
{
|
||||
if (the_file != NULL) {
|
||||
fclose(the_file);
|
||||
the_file = NULL;
|
||||
}
|
||||
if (!the_file)
|
||||
return;
|
||||
rfclose(the_file);
|
||||
the_file = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -227,23 +240,24 @@ void Job1541::WriteSector(void)
|
||||
|
||||
void Job1541::FormatTrack(void)
|
||||
{
|
||||
int track = ram[0x51];
|
||||
|
||||
// Get new ID
|
||||
uint8 buf[256];
|
||||
int sector;
|
||||
int track = ram[0x51];
|
||||
/* Get new ID */
|
||||
uint8 bufnum = ram[0x3d];
|
||||
id1 = ram[0x12 + bufnum];
|
||||
id2 = ram[0x13 + bufnum];
|
||||
|
||||
// Create empty block
|
||||
uint8 buf[256];
|
||||
/* Create empty block */
|
||||
memset(buf, 1, 256);
|
||||
buf[0] = 0x4b;
|
||||
|
||||
// Write block to all sectors on track
|
||||
for(int sector=0; sector<num_sectors[track]; sector++) {
|
||||
write_sector(track, sector, buf);
|
||||
sector2gcr(track, sector);
|
||||
}
|
||||
for(sector=0; sector<num_sectors[track]; sector++)
|
||||
{
|
||||
write_sector(track, sector, buf);
|
||||
sector2gcr(track, sector);
|
||||
}
|
||||
|
||||
// Clear error info (all sectors no error)
|
||||
if (track == 35)
|
||||
@@ -265,8 +279,8 @@ bool Job1541::read_sector(int track, int sector, uint8 *buffer)
|
||||
if ((offset = offset_from_ts(track, sector)) < 0)
|
||||
return false;
|
||||
|
||||
fseek(the_file, offset + image_header, SEEK_SET);
|
||||
fread(buffer, 256, 1, the_file);
|
||||
rfseek(the_file, offset + image_header, SEEK_SET);
|
||||
rfread(buffer, 256, 1, the_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -279,13 +293,12 @@ bool Job1541::read_sector(int track, int sector, uint8 *buffer)
|
||||
bool Job1541::write_sector(int track, int sector, uint8 *buffer)
|
||||
{
|
||||
int offset;
|
||||
|
||||
// Convert track/sector to byte offset in file
|
||||
/* Convert track/sector to byte offset in file */
|
||||
if ((offset = offset_from_ts(track, sector)) < 0)
|
||||
return false;
|
||||
|
||||
fseek(the_file, offset + image_header, SEEK_SET);
|
||||
fwrite(buffer, 256, 1, the_file);
|
||||
rfseek(the_file, offset + image_header, SEEK_SET);
|
||||
rfwrite(buffer, 256, 1, the_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -320,9 +333,7 @@ const uint16 gcr_table[16] = {
|
||||
|
||||
void Job1541::gcr_conv4(uint8 *from, uint8 *to)
|
||||
{
|
||||
uint16 g;
|
||||
|
||||
g = (gcr_table[*from >> 4] << 5) | gcr_table[*from & 15];
|
||||
uint16 g = (gcr_table[*from >> 4] << 5) | gcr_table[*from & 15];
|
||||
*to++ = g >> 2;
|
||||
*to = (g << 6) & 0xc0;
|
||||
from++;
|
||||
@@ -349,9 +360,11 @@ void Job1541::gcr_conv4(uint8 *from, uint8 *to)
|
||||
|
||||
void Job1541::sector2gcr(int track, int sector)
|
||||
{
|
||||
int i;
|
||||
uint8 block[256];
|
||||
uint8 buf[4];
|
||||
uint8 *p = gcr_data + (track-1) * GCR_TRACK_SIZE + sector * GCR_SECTOR_SIZE;
|
||||
uint8 *p = gcr_data + (track-1) * GCR_TRACK_SIZE
|
||||
+ sector * GCR_SECTOR_SIZE;
|
||||
|
||||
read_sector(track, sector, block);
|
||||
|
||||
@@ -380,14 +393,15 @@ void Job1541::sector2gcr(int track, int sector)
|
||||
sum ^= buf[3] = block[2];
|
||||
gcr_conv4(buf, p);
|
||||
p += 5;
|
||||
for (int i=3; i<255; i+=4) {
|
||||
sum ^= buf[0] = block[i];
|
||||
sum ^= buf[1] = block[i+1];
|
||||
sum ^= buf[2] = block[i+2];
|
||||
sum ^= buf[3] = block[i+3];
|
||||
gcr_conv4(buf, p);
|
||||
p += 5;
|
||||
}
|
||||
for (i = 3; i < 255; i += 4)
|
||||
{
|
||||
sum ^= buf[0] = block[i];
|
||||
sum ^= buf[1] = block[i+1];
|
||||
sum ^= buf[2] = block[i+2];
|
||||
sum ^= buf[3] = block[i+3];
|
||||
gcr_conv4(buf, p);
|
||||
p += 5;
|
||||
}
|
||||
sum ^= buf[0] = block[255];
|
||||
buf[1] = sum; // Checksum
|
||||
buf[2] = 0;
|
||||
@@ -399,64 +413,55 @@ void Job1541::sector2gcr(int track, int sector)
|
||||
|
||||
void Job1541::disk2gcr(void)
|
||||
{
|
||||
int track, sector;
|
||||
// Convert all tracks and sectors
|
||||
for (int track=1; track<=NUM_TRACKS; track++)
|
||||
for(int sector=0; sector<num_sectors[track]; sector++)
|
||||
for (track = 1; track <= NUM_TRACKS; track++)
|
||||
for(sector = 0; sector < num_sectors[track]; sector++)
|
||||
sector2gcr(track, sector);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Move R/W head out (lower track numbers)
|
||||
*/
|
||||
|
||||
/* Move R/W head out (lower track numbers) */
|
||||
void Job1541::MoveHeadOut(void)
|
||||
{
|
||||
if (current_halftrack == 2)
|
||||
return;
|
||||
current_halftrack--;
|
||||
gcr_ptr = gcr_track_start = gcr_data + ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE;
|
||||
gcr_ptr = gcr_track_start = gcr_data + ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE;
|
||||
gcr_track_end = gcr_track_start + num_sectors[current_halftrack >> 1] * GCR_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Move R/W head in (higher track numbers)
|
||||
*/
|
||||
|
||||
/* Move R/W head in (higher track numbers) */
|
||||
void Job1541::MoveHeadIn(void)
|
||||
{
|
||||
if (current_halftrack == NUM_TRACKS*2)
|
||||
return;
|
||||
current_halftrack++;
|
||||
gcr_ptr = gcr_track_start = gcr_data + ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE;
|
||||
gcr_ptr = gcr_track_start = gcr_data + ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE;
|
||||
gcr_track_end = gcr_track_start + num_sectors[current_halftrack >> 1] * GCR_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get state
|
||||
*/
|
||||
|
||||
/* Get state */
|
||||
void Job1541::GetState(Job1541State *state)
|
||||
{
|
||||
state->current_halftrack = current_halftrack;
|
||||
state->gcr_ptr = gcr_ptr - gcr_data;
|
||||
state->write_protected = write_protected;
|
||||
state->disk_changed = disk_changed;
|
||||
state->gcr_ptr = gcr_ptr - gcr_data;
|
||||
state->write_protected = write_protected;
|
||||
state->disk_changed = disk_changed;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set state
|
||||
*/
|
||||
|
||||
/* Set state */
|
||||
void Job1541::SetState(Job1541State *state)
|
||||
{
|
||||
current_halftrack = state->current_halftrack;
|
||||
gcr_ptr = gcr_data + state->gcr_ptr;
|
||||
gcr_track_start = gcr_data + ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE;
|
||||
gcr_track_end = gcr_track_start + num_sectors[current_halftrack >> 1] * GCR_SECTOR_SIZE;
|
||||
write_protected = state->write_protected;
|
||||
disk_changed = state->disk_changed;
|
||||
gcr_ptr = gcr_data + state->gcr_ptr;
|
||||
gcr_track_start = gcr_data
|
||||
+ ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE;
|
||||
gcr_track_end = gcr_track_start
|
||||
+ num_sectors[current_halftrack >> 1] * GCR_SECTOR_SIZE;
|
||||
write_protected = state->write_protected;
|
||||
disk_changed = state->disk_changed;
|
||||
}
|
||||
+12
-13
@@ -21,7 +21,7 @@
|
||||
#ifndef _1541JOB_H
|
||||
#define _1541JOB_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <streams/file_stream.h>
|
||||
|
||||
class MOS6502_1541;
|
||||
class Prefs;
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
void disk2gcr(void);
|
||||
|
||||
uint8 *ram; // Pointer to 1541 RAM
|
||||
FILE *the_file; // File pointer for .d64 file
|
||||
RFILE *the_file; // File pointer for .d64 file
|
||||
int image_header; // Length of .d64/.x64 file header
|
||||
|
||||
uint8 id1, id2; // ID of disk
|
||||
@@ -87,14 +87,12 @@ struct Job1541State {
|
||||
|
||||
inline bool Job1541::SyncFound(void)
|
||||
{
|
||||
if (*gcr_ptr == 0xff)
|
||||
return true;
|
||||
else {
|
||||
gcr_ptr++; // Rotate disk
|
||||
if (gcr_ptr == gcr_track_end)
|
||||
gcr_ptr = gcr_track_start;
|
||||
return false;
|
||||
}
|
||||
if (*gcr_ptr == 0xff)
|
||||
return true;
|
||||
gcr_ptr++; /* Rotate disk */
|
||||
if (gcr_ptr == gcr_track_end)
|
||||
gcr_ptr = gcr_track_start;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,11 +115,12 @@ inline uint8 Job1541::ReadGCRByte(void)
|
||||
|
||||
inline uint8 Job1541::WPState(void)
|
||||
{
|
||||
if (disk_changed) { // Disk change -> WP sensor strobe
|
||||
if (disk_changed) // Disk change -> WP sensor strobe
|
||||
{
|
||||
disk_changed = false;
|
||||
return write_protected ? 0x10 : 0;
|
||||
} else
|
||||
return write_protected ? 0 : 0x10;
|
||||
}
|
||||
return write_protected ? 0 : 0x10;
|
||||
}
|
||||
|
||||
#endif
|
||||
+148
-145
@@ -160,55 +160,52 @@ class ScopedSignalBlocker {
|
||||
sigset_t old_set_;
|
||||
};
|
||||
|
||||
static FILE* __tmpfile_dir(const char* tmp_dir) {
|
||||
char buf[PATH_MAX];
|
||||
int path_length = snprintf(buf, sizeof(buf), "%s/tmp.XXXXXXXXXX", tmp_dir);
|
||||
if (path_length >= sizeof(buf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fd;
|
||||
{
|
||||
ScopedSignalBlocker ssb;
|
||||
fd = mkstemp2(buf);
|
||||
if (fd == -1) {
|
||||
static FILE* __tmpfile_dir(const char* tmp_dir)
|
||||
{
|
||||
int fd, old_errno;
|
||||
char buf[PATH_MAX];
|
||||
ScopedSignalBlocker ssb;
|
||||
struct stat sb;
|
||||
FILE *fp = NULL;
|
||||
int path_length = snprintf(buf, sizeof(buf), "%s/tmp.XXXXXXXXXX", tmp_dir);
|
||||
if (path_length >= sizeof(buf))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Unlink the file now so that it's removed when closed.
|
||||
unlink(buf);
|
||||
fd = mkstemp2(buf);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
// Can we still use the file now it's unlinked?
|
||||
// File systems without hard link support won't have the usual Unix semantics.
|
||||
struct stat sb;
|
||||
int rc = fstat(fd, &sb);
|
||||
if (rc == -1) {
|
||||
int old_errno = errno;
|
||||
// Unlink the file now so that it's removed when closed.
|
||||
unlink(buf);
|
||||
|
||||
// Can we still use the file now it's unlinked?
|
||||
// File systems without hard link support won't have the usual Unix semantics.
|
||||
int rc = fstat(fd, &sb);
|
||||
if (rc == -1)
|
||||
{
|
||||
old_errno = errno;
|
||||
close(fd);
|
||||
errno = old_errno;
|
||||
errno = old_errno;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Turn the file descriptor into a FILE*.
|
||||
FILE* fp = fdopen(fd, "w+");
|
||||
if (fp != NULL) {
|
||||
return fp;
|
||||
}
|
||||
// Turn the file descriptor into a FILE*.
|
||||
fp = fdopen(fd, "w+");
|
||||
if (fp)
|
||||
return fp;
|
||||
|
||||
// Failure. Clean up. We already unlinked, so we just need to close.
|
||||
int old_errno = errno;
|
||||
close(fd);
|
||||
errno = old_errno;
|
||||
return NULL;
|
||||
// Failure. Clean up. We already unlinked, so we just need to close.
|
||||
old_errno = errno;
|
||||
close(fd);
|
||||
errno = old_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE* tmpfile2() {
|
||||
|
||||
FILE* tmpfile2(void)
|
||||
{
|
||||
FILE* fp = __tmpfile_dir("/data/data/com.retroarch/tmp");
|
||||
if (fp == NULL) {
|
||||
fp = __tmpfile_dir(P_tmpdir);
|
||||
}
|
||||
if (!fp)
|
||||
return __tmpfile_dir(P_tmpdir);
|
||||
return fp;
|
||||
}
|
||||
|
||||
@@ -222,42 +219,36 @@ static bool parse_t64_file(FILE *f, std::vector<c64_dir_entry> &vec, char *dir_t
|
||||
static bool parse_lynx_file(FILE *f, std::vector<c64_dir_entry> &vec, char *dir_title);
|
||||
static bool parse_p00_file(FILE *f, std::vector<c64_dir_entry> &vec, char *dir_title);
|
||||
|
||||
|
||||
/*
|
||||
* Constructor: Prepare emulation
|
||||
*/
|
||||
|
||||
ArchDrive::ArchDrive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL)
|
||||
{
|
||||
for (int i=0; i<16; i++)
|
||||
unsigned i;
|
||||
for (i = 0; i < 16; i++)
|
||||
file[i] = NULL;
|
||||
Reset();
|
||||
|
||||
// Open archive file
|
||||
/* Open archive file */
|
||||
if (change_arch(filepath))
|
||||
Ready = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Destructor
|
||||
*/
|
||||
|
||||
/* Destructor */
|
||||
ArchDrive::~ArchDrive()
|
||||
{
|
||||
// Close archive file
|
||||
if (the_file) {
|
||||
close_all_channels();
|
||||
fclose(the_file);
|
||||
}
|
||||
if (the_file)
|
||||
{
|
||||
close_all_channels();
|
||||
fclose(the_file);
|
||||
}
|
||||
Ready = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open the archive file
|
||||
*/
|
||||
|
||||
/* Open the archive file */
|
||||
bool ArchDrive::change_arch(const char *path)
|
||||
{
|
||||
FILE *new_file;
|
||||
@@ -271,33 +262,41 @@ bool ArchDrive::change_arch(const char *path)
|
||||
uint8 header[64];
|
||||
fread(header, 1, 64, new_file);
|
||||
bool parsed_ok = false;
|
||||
if (is_t64_header(header)) {
|
||||
archive_type = TYPE_T64;
|
||||
parsed_ok = parse_t64_file(new_file, file_info, dir_title);
|
||||
} else if (is_lynx_header(header)) {
|
||||
archive_type = TYPE_LYNX;
|
||||
parsed_ok = parse_lynx_file(new_file, file_info, dir_title);
|
||||
} else if (is_p00_header(header)) {
|
||||
archive_type = TYPE_P00;
|
||||
parsed_ok = parse_p00_file(new_file, file_info, dir_title);
|
||||
}
|
||||
if (is_t64_header(header))
|
||||
{
|
||||
archive_type = TYPE_T64;
|
||||
parsed_ok = parse_t64_file(new_file, file_info, dir_title);
|
||||
}
|
||||
else if (is_lynx_header(header))
|
||||
{
|
||||
archive_type = TYPE_LYNX;
|
||||
parsed_ok = parse_lynx_file(new_file, file_info, dir_title);
|
||||
}
|
||||
else if (is_p00_header(header))
|
||||
{
|
||||
archive_type = TYPE_P00;
|
||||
parsed_ok = parse_p00_file(new_file, file_info, dir_title);
|
||||
}
|
||||
|
||||
if (!parsed_ok) {
|
||||
fclose(new_file);
|
||||
if (the_file) {
|
||||
close_all_channels();
|
||||
fclose(the_file);
|
||||
the_file = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!parsed_ok)
|
||||
{
|
||||
fclose(new_file);
|
||||
if (the_file)
|
||||
{
|
||||
close_all_channels();
|
||||
fclose(the_file);
|
||||
the_file = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Close old archive if open, and set new file
|
||||
if (the_file) {
|
||||
close_all_channels();
|
||||
fclose(the_file);
|
||||
the_file = NULL;
|
||||
}
|
||||
if (the_file)
|
||||
{
|
||||
close_all_channels();
|
||||
fclose(the_file);
|
||||
the_file = NULL;
|
||||
}
|
||||
the_file = new_file;
|
||||
return true;
|
||||
}
|
||||
@@ -314,40 +313,40 @@ uint8 ArchDrive::Open(int channel, const uint8 *name, int name_len)
|
||||
set_error(ERR_OK);
|
||||
|
||||
// Channel 15: Execute file name as command
|
||||
if (channel == 15) {
|
||||
execute_cmd(name, name_len);
|
||||
return ST_OK;
|
||||
}
|
||||
if (channel == 15)
|
||||
{
|
||||
execute_cmd(name, name_len);
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
// Close previous file if still open
|
||||
if (file[channel]) {
|
||||
fclose(file[channel]);
|
||||
file[channel] = NULL;
|
||||
}
|
||||
if (file[channel])
|
||||
{
|
||||
fclose(file[channel]);
|
||||
file[channel] = NULL;
|
||||
}
|
||||
|
||||
if (name[0] == '#') {
|
||||
set_error(ERR_NOCHANNEL);
|
||||
return ST_OK;
|
||||
}
|
||||
if (name[0] == '#')
|
||||
{
|
||||
set_error(ERR_NOCHANNEL);
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
if (the_file == NULL) {
|
||||
set_error(ERR_NOTREADY);
|
||||
return ST_OK;
|
||||
}
|
||||
if (!the_file)
|
||||
{
|
||||
set_error(ERR_NOTREADY);
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
if (name[0] == '$')
|
||||
return open_directory(channel, name + 1, name_len - 1);
|
||||
|
||||
return open_file(channel, name, name_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open file
|
||||
*/
|
||||
|
||||
/* Open file */
|
||||
uint8 ArchDrive::open_file(int channel, const uint8 *name, int name_len)
|
||||
{
|
||||
bool writing;
|
||||
uint8 plain_name[NAMEBUF_LENGTH];
|
||||
int plain_name_len;
|
||||
int mode = FMODE_READ;
|
||||
@@ -362,7 +361,7 @@ uint8 ArchDrive::open_file(int channel, const uint8 *name, int name_len)
|
||||
type = FTYPE_PRG;
|
||||
}
|
||||
|
||||
bool writing = (mode == FMODE_WRITE || mode == FMODE_APPEND);
|
||||
writing = (mode == FMODE_WRITE || mode == FMODE_APPEND);
|
||||
|
||||
// Wildcards are only allowed on reading
|
||||
if (writing && (strchr((const char *)plain_name, '*') || strchr((const char *)plain_name, '?'))) {
|
||||
@@ -423,13 +422,14 @@ uint8 ArchDrive::open_file(int channel, const uint8 *name, int name_len)
|
||||
// Return true if name 'n' matches pattern 'p'
|
||||
static bool match(const uint8 *p, int p_len, const uint8 *n)
|
||||
{
|
||||
while (p_len-- > 0) {
|
||||
if (*p == '*') // Wildcard '*' matches all following characters
|
||||
return true;
|
||||
if ((*p != *n) && (*p != '?')) // Wildcard '?' matches single character
|
||||
return false;
|
||||
p++; n++;
|
||||
}
|
||||
while (p_len-- > 0)
|
||||
{
|
||||
if (*p == '*') // Wildcard '*' matches all following characters
|
||||
return true;
|
||||
if ((*p != *n) && (*p != '?')) // Wildcard '?' matches single character
|
||||
return false;
|
||||
p++; n++;
|
||||
}
|
||||
|
||||
return *n == 0;
|
||||
}
|
||||
@@ -437,10 +437,11 @@ static bool match(const uint8 *p, int p_len, const uint8 *n)
|
||||
bool ArchDrive::find_first_file(const uint8 *pattern, int pattern_len, int &num)
|
||||
{
|
||||
std::vector<c64_dir_entry>::const_iterator i, end = file_info.end();
|
||||
for (i = file_info.begin(), num = 0; i != end; i++, num++) {
|
||||
if (match(pattern, pattern_len, (uint8 *)i->name))
|
||||
return true;
|
||||
}
|
||||
for (i = file_info.begin(), num = 0; i != end; i++, num++)
|
||||
{
|
||||
if (match(pattern, pattern_len, (uint8 *)i->name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -451,19 +452,22 @@ bool ArchDrive::find_first_file(const uint8 *pattern, int pattern_len, int &num)
|
||||
|
||||
uint8 ArchDrive::open_directory(int channel, const uint8 *pattern, int pattern_len)
|
||||
{
|
||||
uint8 *t;
|
||||
// Special treatment for "$0"
|
||||
if (pattern[0] == '0' && pattern_len == 1) {
|
||||
pattern++;
|
||||
pattern_len--;
|
||||
}
|
||||
if (pattern[0] == '0' && pattern_len == 1)
|
||||
{
|
||||
pattern++;
|
||||
pattern_len--;
|
||||
}
|
||||
|
||||
// Skip everything before the ':' in the pattern
|
||||
uint8 *t = (uint8 *)memchr(pattern, ':', pattern_len);
|
||||
if (t) {
|
||||
t++;
|
||||
pattern_len -= t - pattern;
|
||||
pattern = t;
|
||||
}
|
||||
t = (uint8 *)memchr(pattern, ':', pattern_len);
|
||||
if (t)
|
||||
{
|
||||
t++;
|
||||
pattern_len -= t - pattern;
|
||||
pattern = t;
|
||||
}
|
||||
|
||||
#if defined(ANDROID) || defined(__ANDROID__)
|
||||
// Create temporary file
|
||||
@@ -719,8 +723,7 @@ static bool is_t64_header(const uint8 *header)
|
||||
|| memcmp(header, "C64 tape image", 14) == 0
|
||||
|| memcmp(header, "C64S tape image", 15) == 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_lynx_header(const uint8 *header)
|
||||
@@ -894,26 +897,26 @@ static bool parse_p00_file(FILE *f, std::vector<c64_dir_entry> &vec, char *dir_t
|
||||
|
||||
bool ReadArchDirectory(const char *path, std::vector<c64_dir_entry> &vec)
|
||||
{
|
||||
// Open file
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (f) {
|
||||
// Open file
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (f)
|
||||
{
|
||||
// Read header
|
||||
uint8 header[64];
|
||||
fread(header, 1, sizeof(header), f);
|
||||
|
||||
// Read header
|
||||
uint8 header[64];
|
||||
fread(header, 1, sizeof(header), f);
|
||||
// Determine archive type and parse archive
|
||||
bool result = false;
|
||||
char dir_title[16];
|
||||
if (is_t64_header(header))
|
||||
result = parse_t64_file(f, vec, dir_title);
|
||||
else if (is_lynx_header(header))
|
||||
result = parse_lynx_file(f, vec, dir_title);
|
||||
else if (is_p00_header(header))
|
||||
result = parse_p00_file(f, vec, dir_title);
|
||||
|
||||
// Determine archive type and parse archive
|
||||
bool result = false;
|
||||
char dir_title[16];
|
||||
if (is_t64_header(header))
|
||||
result = parse_t64_file(f, vec, dir_title);
|
||||
else if (is_lynx_header(header))
|
||||
result = parse_lynx_file(f, vec, dir_title);
|
||||
else if (is_p00_header(header))
|
||||
result = parse_p00_file(f, vec, dir_title);
|
||||
|
||||
fclose(f);
|
||||
return result;
|
||||
} else
|
||||
return false;
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
+78
-69
@@ -18,8 +18,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <sys/time.h> /* TODO/FIXME - get rid of gettimeofday */
|
||||
|
||||
#include <libretro.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
@@ -48,17 +46,29 @@ bool IsFrodoSC = true;
|
||||
bool IsFrodoSC = false;
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
extern "C" {
|
||||
RFILE* rfopen(const char *path, const char *mode);
|
||||
int64_t rfseek(RFILE* stream, int64_t offset, int origin);
|
||||
int64_t rftell(RFILE* stream);
|
||||
int rfclose(RFILE* stream);
|
||||
int64_t rfread(void* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream);
|
||||
int64_t rfwrite(void const* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream);
|
||||
int rfgetc(RFILE* stream);
|
||||
int rfputc(int character, RFILE * stream);
|
||||
int rfprintf(RFILE * stream, const char * format, ...);
|
||||
}
|
||||
extern retro_input_state_t input_state_cb;
|
||||
#ifndef NO_LIBCO
|
||||
extern cothread_t mainThread;
|
||||
extern cothread_t emuThread;
|
||||
#endif
|
||||
extern int pauseg,retro_quit;
|
||||
extern void pause_select();
|
||||
extern void pause_select(void);
|
||||
extern int SHOWKEY;
|
||||
|
||||
static struct timeval tv_start;
|
||||
|
||||
/*
|
||||
* Constructor: Allocate objects and memory
|
||||
*/
|
||||
@@ -277,14 +287,14 @@ void C64::PatchKernal(bool fast_reset, bool emul_1541_proc)
|
||||
/* Save RAM contents */
|
||||
void C64::SaveRAM(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
if (!(f = fopen(filename, "wb")))
|
||||
RFILE *f;
|
||||
if (!(f = rfopen(filename, "wb")))
|
||||
return;
|
||||
fwrite((void*)RAM, 1, 0x10000, f);
|
||||
fwrite((void*)Color, 1, 0x400, f);
|
||||
rfwrite((void*)RAM, 1, 0x10000, f);
|
||||
rfwrite((void*)Color, 1, 0x400, f);
|
||||
if (ThePrefs.Emul1541Proc)
|
||||
fwrite((void*)RAM1541, 1, 0x800, f);
|
||||
fclose(f);
|
||||
rfwrite((void*)RAM1541, 1, 0x800, f);
|
||||
rfclose(f);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -294,7 +304,7 @@ void C64::SaveRAM(char *filename)
|
||||
* 1: OK
|
||||
* -1: Instruction not completed
|
||||
*/
|
||||
int C64::SaveCPUState(FILE *f)
|
||||
int C64::SaveCPUState(RFILE *f)
|
||||
{
|
||||
int i;
|
||||
MOS6510State state;
|
||||
@@ -303,9 +313,9 @@ int C64::SaveCPUState(FILE *f)
|
||||
if (!state.instruction_complete)
|
||||
return -1;
|
||||
|
||||
i = fwrite(RAM, 0x10000, 1, f);
|
||||
i += fwrite(Color, 0x400, 1, f);
|
||||
i += fwrite((void*)&state, sizeof(state), 1, f);
|
||||
i = rfwrite(RAM, 0x10000, 1, f);
|
||||
i += rfwrite(Color, 0x400, 1, f);
|
||||
i += rfwrite((void*)&state, sizeof(state), 1, f);
|
||||
|
||||
return i == 3;
|
||||
}
|
||||
@@ -315,12 +325,12 @@ int C64::SaveCPUState(FILE *f)
|
||||
* Load CPU state from snapshot
|
||||
*/
|
||||
|
||||
bool C64::LoadCPUState(FILE *f)
|
||||
bool C64::LoadCPUState(RFILE *f)
|
||||
{
|
||||
MOS6510State state;
|
||||
int i = fread(RAM, 0x10000, 1, f);
|
||||
i += fread(Color, 0x400, 1, f);
|
||||
i += fread((void*)&state, sizeof(state), 1, f);
|
||||
int i = rfread(RAM, 0x10000, 1, f);
|
||||
i += rfread(Color, 0x400, 1, f);
|
||||
i += rfread((void*)&state, sizeof(state), 1, f);
|
||||
|
||||
if (i == 3)
|
||||
{
|
||||
@@ -339,7 +349,7 @@ bool C64::LoadCPUState(FILE *f)
|
||||
* -1: Instruction not completed
|
||||
*/
|
||||
|
||||
int C64::Save1541State(FILE *f)
|
||||
int C64::Save1541State(RFILE *f)
|
||||
{
|
||||
int i;
|
||||
MOS6502State state;
|
||||
@@ -348,8 +358,8 @@ int C64::Save1541State(FILE *f)
|
||||
if (!state.idle && !state.instruction_complete)
|
||||
return -1;
|
||||
|
||||
i = fwrite(RAM1541, 0x800, 1, f);
|
||||
i += fwrite((void*)&state, sizeof(state), 1, f);
|
||||
i = rfwrite(RAM1541, 0x800, 1, f);
|
||||
i += rfwrite((void*)&state, sizeof(state), 1, f);
|
||||
return i == 2;
|
||||
}
|
||||
|
||||
@@ -358,11 +368,11 @@ int C64::Save1541State(FILE *f)
|
||||
* Load 1541 state from snapshot
|
||||
*/
|
||||
|
||||
bool C64::Load1541State(FILE *f)
|
||||
bool C64::Load1541State(RFILE *f)
|
||||
{
|
||||
MOS6502State state;
|
||||
int i = fread(RAM1541, 0x800, 1, f);
|
||||
i += fread((void*)&state, sizeof(state), 1, f);
|
||||
int i = rfread(RAM1541, 0x800, 1, f);
|
||||
i += rfread((void*)&state, sizeof(state), 1, f);
|
||||
|
||||
if (i == 2)
|
||||
{
|
||||
@@ -377,11 +387,11 @@ bool C64::Load1541State(FILE *f)
|
||||
* Save VIC state to snapshot
|
||||
*/
|
||||
|
||||
bool C64::SaveVICState(FILE *f)
|
||||
bool C64::SaveVICState(RFILE *f)
|
||||
{
|
||||
MOS6569State state;
|
||||
TheVIC->GetState(&state);
|
||||
return fwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
return rfwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -389,10 +399,10 @@ bool C64::SaveVICState(FILE *f)
|
||||
* Load VIC state from snapshot
|
||||
*/
|
||||
|
||||
bool C64::LoadVICState(FILE *f)
|
||||
bool C64::LoadVICState(RFILE *f)
|
||||
{
|
||||
MOS6569State state;
|
||||
if (fread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
if (rfread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
{
|
||||
TheVIC->SetState(&state);
|
||||
return true;
|
||||
@@ -405,11 +415,11 @@ bool C64::LoadVICState(FILE *f)
|
||||
* Save SID state to snapshot
|
||||
*/
|
||||
|
||||
bool C64::SaveSIDState(FILE *f)
|
||||
bool C64::SaveSIDState(RFILE *f)
|
||||
{
|
||||
MOS6581State state;
|
||||
TheSID->GetState(&state);
|
||||
return fwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
return rfwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -417,10 +427,10 @@ bool C64::SaveSIDState(FILE *f)
|
||||
* Load SID state from snapshot
|
||||
*/
|
||||
|
||||
bool C64::LoadSIDState(FILE *f)
|
||||
bool C64::LoadSIDState(RFILE *f)
|
||||
{
|
||||
MOS6581State state;
|
||||
if (fread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
if (rfread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
{
|
||||
TheSID->SetState(&state);
|
||||
return true;
|
||||
@@ -433,14 +443,14 @@ bool C64::LoadSIDState(FILE *f)
|
||||
* Save CIA states to snapshot
|
||||
*/
|
||||
|
||||
bool C64::SaveCIAState(FILE *f)
|
||||
bool C64::SaveCIAState(RFILE *f)
|
||||
{
|
||||
MOS6526State state;
|
||||
TheCIA1->GetState(&state);
|
||||
if (fwrite((void*)&state, sizeof(state), 1, f) == 1)
|
||||
if (rfwrite((void*)&state, sizeof(state), 1, f) == 1)
|
||||
{
|
||||
TheCIA2->GetState(&state);
|
||||
return fwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
return rfwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -450,13 +460,13 @@ bool C64::SaveCIAState(FILE *f)
|
||||
* Load CIA states from snapshot
|
||||
*/
|
||||
|
||||
bool C64::LoadCIAState(FILE *f)
|
||||
bool C64::LoadCIAState(RFILE *f)
|
||||
{
|
||||
MOS6526State state;
|
||||
if (fread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
if (rfread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
{
|
||||
TheCIA1->SetState(&state);
|
||||
if (fread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
if (rfread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
{
|
||||
TheCIA2->SetState(&state);
|
||||
return true;
|
||||
@@ -470,11 +480,11 @@ bool C64::LoadCIAState(FILE *f)
|
||||
* Save 1541 GCR state to snapshot
|
||||
*/
|
||||
|
||||
bool C64::Save1541JobState(FILE *f)
|
||||
bool C64::Save1541JobState(RFILE *f)
|
||||
{
|
||||
Job1541State state;
|
||||
TheJob1541->GetState(&state);
|
||||
return fwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
return rfwrite((void*)&state, sizeof(state), 1, f) == 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -482,10 +492,10 @@ bool C64::Save1541JobState(FILE *f)
|
||||
* Load 1541 GCR state from snapshot
|
||||
*/
|
||||
|
||||
bool C64::Load1541JobState(FILE *f)
|
||||
bool C64::Load1541JobState(RFILE *f)
|
||||
{
|
||||
Job1541State state;
|
||||
if (fread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
if (rfread((void*)&state, sizeof(state), 1, f) == 1)
|
||||
{
|
||||
TheJob1541->SetState(&state);
|
||||
return true;
|
||||
@@ -521,19 +531,19 @@ bool C64::Load1541JobState(FILE *f)
|
||||
|
||||
void C64::SaveSnapshot(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
RFILE *f;
|
||||
uint8 flags;
|
||||
uint8 delay;
|
||||
int stat;
|
||||
if (!(f = fopen(filename, "wb")))
|
||||
if (!(f = rfopen(filename, "wb")))
|
||||
return;
|
||||
|
||||
fprintf(f, "%s%c", SNAPSHOT_HEADER, 10);
|
||||
fputc(0, f); // Version number 0
|
||||
rfprintf(f, "%s%c", SNAPSHOT_HEADER, 10);
|
||||
rfputc(0, f); // Version number 0
|
||||
flags = 0;
|
||||
if (ThePrefs.Emul1541Proc)
|
||||
flags |= SNAPSHOT_1541;
|
||||
fputc(flags, f);
|
||||
rfputc(flags, f);
|
||||
SaveVICState(f);
|
||||
SaveSIDState(f);
|
||||
SaveCIAState(f);
|
||||
@@ -549,16 +559,16 @@ void C64::SaveSnapshot(char *filename)
|
||||
delay++;
|
||||
}
|
||||
} while (stat == -1);
|
||||
fputc(delay, f); // Number of cycles the
|
||||
rfputc(delay, f); // Number of cycles the
|
||||
// saved CPUC64 lags behind the previous chips
|
||||
#else
|
||||
SaveCPUState(f);
|
||||
fputc(0, f); // No delay
|
||||
rfputc(0, f); // No delay
|
||||
#endif
|
||||
|
||||
if (ThePrefs.Emul1541Proc)
|
||||
{
|
||||
fwrite(ThePrefs.DrivePath[0], 256, 1, f);
|
||||
rfwrite(ThePrefs.DrivePath[0], 256, 1, f);
|
||||
#ifdef FRODO_SC
|
||||
delay = 0;
|
||||
do
|
||||
@@ -569,14 +579,14 @@ void C64::SaveSnapshot(char *filename)
|
||||
delay++;
|
||||
}
|
||||
} while (stat == -1);
|
||||
fputc(delay, f);
|
||||
rfputc(delay, f);
|
||||
#else
|
||||
Save1541State(f);
|
||||
fputc(0, f); // No delay
|
||||
rfputc(0, f); // No delay
|
||||
#endif
|
||||
Save1541JobState(f);
|
||||
}
|
||||
fclose(f);
|
||||
rfclose(f);
|
||||
}
|
||||
|
||||
|
||||
@@ -586,8 +596,8 @@ void C64::SaveSnapshot(char *filename)
|
||||
|
||||
bool C64::LoadSnapshot(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
if ((f = fopen(filename, "rb")))
|
||||
RFILE *f;
|
||||
if ((f = rfopen(filename, "rb")))
|
||||
{
|
||||
uint8 delay, i;
|
||||
char Header[] = SNAPSHOT_HEADER;
|
||||
@@ -597,7 +607,7 @@ bool C64::LoadSnapshot(char *filename)
|
||||
and so forth utterly fail here. */
|
||||
while (*b > 32)
|
||||
{
|
||||
if ((c = fgetc(f)) != *b++)
|
||||
if ((c = rfgetc(f)) != *b++)
|
||||
{
|
||||
b = NULL;
|
||||
break;
|
||||
@@ -613,15 +623,15 @@ bool C64::LoadSnapshot(char *filename)
|
||||
#endif
|
||||
|
||||
while (c != 10)
|
||||
c = fgetc(f); // Shouldn't be necessary
|
||||
if (fgetc(f) != 0)
|
||||
c = rfgetc(f); // Shouldn't be necessary
|
||||
if (rfgetc(f) != 0)
|
||||
{
|
||||
fclose(f);
|
||||
rfclose(f);
|
||||
return false;
|
||||
}
|
||||
flags = fgetc(f);
|
||||
flags = rfgetc(f);
|
||||
#ifndef FRODO_SC
|
||||
vicptr = ftell(f);
|
||||
vicptr = rftell(f);
|
||||
#endif
|
||||
|
||||
error |= !LoadVICState(f);
|
||||
@@ -629,7 +639,7 @@ bool C64::LoadSnapshot(char *filename)
|
||||
error |= !LoadCIAState(f);
|
||||
error |= !LoadCPUState(f);
|
||||
|
||||
delay = fgetc(f); // Number of cycles the 6510 is ahead of the previous chips
|
||||
delay = rfgetc(f); // Number of cycles the 6510 is ahead of the previous chips
|
||||
#ifdef FRODO_SC
|
||||
// Make the other chips "catch up" with the 6510
|
||||
for (i=0; i<delay; i++)
|
||||
@@ -643,7 +653,7 @@ bool C64::LoadSnapshot(char *filename)
|
||||
{
|
||||
Prefs *prefs = new Prefs(ThePrefs);
|
||||
// First switch on emulation
|
||||
error |= (fread(prefs->DrivePath[0], 256, 1, f)
|
||||
error |= (rfread(prefs->DrivePath[0], 256, 1, f)
|
||||
!= 1);
|
||||
prefs->Emul1541Proc = true;
|
||||
NewPrefs(prefs);
|
||||
@@ -653,7 +663,7 @@ bool C64::LoadSnapshot(char *filename)
|
||||
// Then read the context
|
||||
error |= !Load1541State(f);
|
||||
|
||||
delay = fgetc(f);
|
||||
delay = rfgetc(f);
|
||||
// Number of cycles
|
||||
// the 6502 is ahead of the previous chips
|
||||
#ifdef FRODO_SC
|
||||
@@ -679,11 +689,11 @@ bool C64::LoadSnapshot(char *filename)
|
||||
}
|
||||
|
||||
#ifndef FRODO_SC
|
||||
fseek(f, vicptr, SEEK_SET);
|
||||
rfseek(f, vicptr, SEEK_SET);
|
||||
LoadVICState(f); // Load VIC data twice
|
||||
// in SL (is REALLY necessary sometimes!)
|
||||
#endif
|
||||
fclose(f);
|
||||
rfclose(f);
|
||||
|
||||
if (error)
|
||||
{
|
||||
@@ -692,7 +702,7 @@ bool C64::LoadSnapshot(char *filename)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
fclose(f);
|
||||
rfclose(f);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -712,7 +722,6 @@ void C64::c64_ctor1(void)
|
||||
|
||||
void C64::c64_ctor2(void)
|
||||
{
|
||||
gettimeofday(&tv_start, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,14 +23,18 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// Sizes of memory areas
|
||||
const int C64_RAM_SIZE = 0x10000;
|
||||
const int COLOR_RAM_SIZE = 0x400;
|
||||
const int BASIC_ROM_SIZE = 0x2000;
|
||||
#include <streams/file_stream.h>
|
||||
|
||||
/* TODO/FIXME - most if not all the file I/O should eventually be removed */
|
||||
|
||||
/* Sizes of memory areas */
|
||||
const int C64_RAM_SIZE = 0x10000;
|
||||
const int COLOR_RAM_SIZE = 0x400;
|
||||
const int BASIC_ROM_SIZE = 0x2000;
|
||||
const int KERNAL_ROM_SIZE = 0x2000;
|
||||
const int CHAR_ROM_SIZE = 0x1000;
|
||||
const int DRIVE_RAM_SIZE = 0x800;
|
||||
const int DRIVE_ROM_SIZE = 0x4000;
|
||||
const int CHAR_ROM_SIZE = 0x1000;
|
||||
const int DRIVE_RAM_SIZE = 0x800;
|
||||
const int DRIVE_ROM_SIZE = 0x4000;
|
||||
|
||||
|
||||
// false: Frodo, true: FrodoSC
|
||||
@@ -62,18 +66,18 @@ public:
|
||||
void SaveRAM(char *filename);
|
||||
void SaveSnapshot(char *filename);
|
||||
bool LoadSnapshot(char *filename);
|
||||
int SaveCPUState(FILE *f);
|
||||
int Save1541State(FILE *f);
|
||||
bool Save1541JobState(FILE *f);
|
||||
bool SaveVICState(FILE *f);
|
||||
bool SaveSIDState(FILE *f);
|
||||
bool SaveCIAState(FILE *f);
|
||||
bool LoadCPUState(FILE *f);
|
||||
bool Load1541State(FILE *f);
|
||||
bool Load1541JobState(FILE *f);
|
||||
bool LoadVICState(FILE *f);
|
||||
bool LoadSIDState(FILE *f);
|
||||
bool LoadCIAState(FILE *f);
|
||||
int SaveCPUState(RFILE *f);
|
||||
int Save1541State(RFILE *f);
|
||||
bool Save1541JobState(RFILE *f);
|
||||
bool SaveVICState(RFILE *f);
|
||||
bool SaveSIDState(RFILE *f);
|
||||
bool SaveCIAState(RFILE *f);
|
||||
bool LoadCPUState(RFILE *f);
|
||||
bool Load1541State(RFILE *f);
|
||||
bool Load1541JobState(RFILE *f);
|
||||
bool LoadVICState(RFILE *f);
|
||||
bool LoadSIDState(RFILE *f);
|
||||
bool LoadCIAState(RFILE *f);
|
||||
|
||||
uint8 *RAM, *Basic, *Kernal,
|
||||
*Char, *Color; // C64
|
||||
|
||||
+76
-70
@@ -41,6 +41,8 @@
|
||||
* Sent before the last byte, not after it.
|
||||
*/
|
||||
|
||||
#include <streams/file_stream.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "IEC.h"
|
||||
@@ -51,15 +53,15 @@
|
||||
#include "Display.h"
|
||||
#include "main.h"
|
||||
|
||||
// IEC command codes
|
||||
/* IEC command codes */
|
||||
enum
|
||||
{
|
||||
CMD_DATA = 0x60, // Data transfer
|
||||
CMD_CLOSE = 0xe0, // Close channel
|
||||
CMD_OPEN = 0xf0 // Open channel
|
||||
CMD_DATA = 0x60, /* Data transfer */
|
||||
CMD_CLOSE = 0xe0, /* Close channel */
|
||||
CMD_OPEN = 0xf0 /* Open channel */
|
||||
};
|
||||
|
||||
// IEC ATN codes
|
||||
/* IEC ATN codes */
|
||||
enum
|
||||
{
|
||||
ATN_LISTEN = 0x20,
|
||||
@@ -68,38 +70,43 @@ enum
|
||||
ATN_UNTALK = 0x50
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
extern "C" {
|
||||
RFILE* rfopen(const char *path, const char *mode);
|
||||
int64_t rfseek(RFILE* stream, int64_t offset, int origin);
|
||||
int64_t rftell(RFILE* stream);
|
||||
int rfclose(RFILE* stream);
|
||||
int64_t rfread(void* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor: Initialize variables
|
||||
*/
|
||||
|
||||
/* Constructor: Initialize variables */
|
||||
Drive *IEC::create_drive(const char *path)
|
||||
{
|
||||
int type;
|
||||
// Mount host directory
|
||||
if (IsDirectory(path))
|
||||
return new FSDrive(this, path);
|
||||
if (IsDirectory(path))
|
||||
return new FSDrive(this, path);
|
||||
// Not a directory, check for mountable file type
|
||||
if (IsMountableFile(path, type))
|
||||
{
|
||||
// Not a directory, check for mountable file type
|
||||
int type;
|
||||
if (IsMountableFile(path, type))
|
||||
{
|
||||
if (type == FILE_IMAGE)
|
||||
// Mount disk image
|
||||
return new ImageDrive(this, path);
|
||||
// Mount archive type file
|
||||
return new ArchDrive(this, path);
|
||||
}
|
||||
}
|
||||
if (type == FILE_IMAGE)
|
||||
// Mount disk image
|
||||
return new ImageDrive(this, path);
|
||||
// Mount archive type file
|
||||
return new ArchDrive(this, path);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IEC::IEC(C64Display *display) : the_display(display)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Create drives 8..11
|
||||
/* Create drives 8..11 */
|
||||
for (i=0; i<4; i++)
|
||||
drive[i] = NULL; // Important because UpdateLEDs is called from the drive constructors (via set_error)
|
||||
drive[i] = NULL; /* Important because UpdateLEDs
|
||||
is called from the drive
|
||||
constructors (via set_error) */
|
||||
|
||||
if (!ThePrefs.Emul1541Proc)
|
||||
{
|
||||
@@ -107,18 +114,17 @@ IEC::IEC(C64Display *display) : the_display(display)
|
||||
drive[i] = create_drive(ThePrefs.DrivePath[i]);
|
||||
}
|
||||
|
||||
listener_active = talker_active = false;
|
||||
listener_active = false;
|
||||
talker_active = false;
|
||||
listening = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Destructor: Delete drives
|
||||
*/
|
||||
|
||||
/* Destructor: Delete drives */
|
||||
IEC::~IEC()
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
delete drive[i];
|
||||
}
|
||||
|
||||
@@ -129,8 +135,9 @@ IEC::~IEC()
|
||||
|
||||
void IEC::Reset(void)
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
if (drive[i] != NULL && drive[i]->Ready)
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (drive[i] && drive[i]->Ready)
|
||||
drive[i]->Reset();
|
||||
|
||||
UpdateLEDs();
|
||||
@@ -145,13 +152,18 @@ void IEC::Reset(void)
|
||||
|
||||
void IEC::NewPrefs(Prefs *prefs)
|
||||
{
|
||||
// Delete and recreate all changed drives
|
||||
for (int i=0; i<4; i++)
|
||||
int i;
|
||||
/* Delete and recreate all changed drives */
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (strcmp(ThePrefs.DrivePath[i], prefs->DrivePath[i]) || ThePrefs.Emul1541Proc != prefs->Emul1541Proc)
|
||||
if ( strcmp(ThePrefs.DrivePath[i],
|
||||
prefs->DrivePath[i])
|
||||
|| ThePrefs.Emul1541Proc != prefs->Emul1541Proc)
|
||||
{
|
||||
delete drive[i];
|
||||
drive[i] = NULL; // Important because UpdateLEDs is called from drive constructors (via set_error())
|
||||
drive[i] = NULL; /* Important because UpdateLEDs
|
||||
is called from drive
|
||||
constructors (via set_error()) */
|
||||
if (!prefs->Emul1541Proc)
|
||||
drive[i] = create_drive(prefs->DrivePath[i]);
|
||||
}
|
||||
@@ -161,21 +173,20 @@ void IEC::NewPrefs(Prefs *prefs)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update drive LED display
|
||||
*/
|
||||
|
||||
/* Update drive LED display */
|
||||
void IEC::UpdateLEDs(void)
|
||||
{
|
||||
if (drive[0] != NULL && drive[1] != NULL && drive[2] != NULL && drive[3] != NULL)
|
||||
the_display->UpdateLEDs(drive[0]->LED, drive[1]->LED, drive[2]->LED, drive[3]->LED);
|
||||
if (
|
||||
drive[0] != NULL
|
||||
&& drive[1] != NULL
|
||||
&& drive[2] != NULL
|
||||
&& drive[3] != NULL)
|
||||
the_display->UpdateLEDs(drive[0]->LED,
|
||||
drive[1]->LED, drive[2]->LED, drive[3]->LED);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output one byte
|
||||
*/
|
||||
|
||||
/* Output one byte */
|
||||
uint8 IEC::Out(uint8 byte, bool eoi)
|
||||
{
|
||||
if (listener_active)
|
||||
@@ -189,10 +200,7 @@ uint8 IEC::Out(uint8 byte, bool eoi)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output one byte with ATN (Talk/Listen/Untalk/Unlisten)
|
||||
*/
|
||||
|
||||
/* Output one byte with ATN (Talk/Listen/Untalk/Unlisten) */
|
||||
uint8 IEC::OutATN(uint8 byte)
|
||||
{
|
||||
received_cmd = sec_addr = 0; // Command is sent with secondary address
|
||||
@@ -393,7 +401,6 @@ uint8 IEC::sec_talk(void)
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Byte after Open command: Store character in file name, open file on EOI
|
||||
*/
|
||||
@@ -417,11 +424,7 @@ uint8 IEC::open_out(uint8 byte, bool eoi)
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write byte to channel
|
||||
*/
|
||||
|
||||
/* Write byte to channel */
|
||||
uint8 IEC::data_out(uint8 byte, bool eoi)
|
||||
{
|
||||
return listener->Write(sec_addr, byte, eoi);
|
||||
@@ -493,8 +496,8 @@ void Drive::set_error(int error, int track, int sector)
|
||||
{
|
||||
// Write error message to buffer
|
||||
sprintf(error_buf, Errors_1541[error], track, sector);
|
||||
error_ptr = error_buf;
|
||||
error_len = strlen(error_buf);
|
||||
error_ptr = error_buf;
|
||||
error_len = strlen(error_buf);
|
||||
current_error = error;
|
||||
|
||||
// Set drive condition
|
||||
@@ -515,6 +518,7 @@ void Drive::set_error(int error, int track, int sector)
|
||||
|
||||
void Drive::parse_file_name(const uint8 *src, int src_len, uint8 *dest, int &dest_len, int &mode, int &type, int &rec_len, bool convert_charset)
|
||||
{
|
||||
uint8 *q;
|
||||
// If the string contains a ':', the file name starts after that
|
||||
const uint8 *p = (const uint8 *)memchr(src, ':', src_len);
|
||||
if (p)
|
||||
@@ -527,7 +531,7 @@ void Drive::parse_file_name(const uint8 *src, int src_len, uint8 *dest, int &des
|
||||
|
||||
// Transfer file name upto ','
|
||||
dest_len = 0;
|
||||
uint8 *q = dest;
|
||||
q = dest;
|
||||
while (*p != ',' && src_len-- > 0)
|
||||
{
|
||||
if (convert_charset)
|
||||
@@ -940,17 +944,18 @@ void petscii2ascii(char *dest, const uint8 *src, int n)
|
||||
|
||||
bool IsMountableFile(const char *path, int &type)
|
||||
{
|
||||
// Read header and determine file size
|
||||
int64_t size;
|
||||
/* Read header and determine file size */
|
||||
uint8 header[64];
|
||||
memset(header, 0, sizeof(header));
|
||||
FILE *f = fopen(path, "rb");
|
||||
RFILE *f = rfopen(path, "rb");
|
||||
if (!f)
|
||||
return false;
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(header, 1, sizeof(header), f);
|
||||
fclose(f);
|
||||
rfseek(f, 0, SEEK_END);
|
||||
size = rftell(f);
|
||||
rfseek(f, 0, SEEK_SET);
|
||||
rfread(header, 1, sizeof(header), f);
|
||||
rfclose(f);
|
||||
|
||||
if (IsImageFile(path, header, size))
|
||||
{
|
||||
@@ -967,11 +972,12 @@ bool IsMountableFile(const char *path, int &type)
|
||||
|
||||
|
||||
/*
|
||||
* Read directory of mountable disk image or archive file into c64_dir_entry vector,
|
||||
* Read directory of mountable disk image
|
||||
* or archive file into c64_dir_entry vector,
|
||||
* returns false on error
|
||||
*/
|
||||
|
||||
bool ReadDirectory(const char *path, int type, std::vector<c64_dir_entry> &vec)
|
||||
bool ReadDirectory(const char *path, int type,
|
||||
std::vector<c64_dir_entry> &vec)
|
||||
{
|
||||
vec.clear();
|
||||
switch (type)
|
||||
|
||||
+37
-45
@@ -26,6 +26,14 @@
|
||||
#include <unistd.h> /* getcwd */
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <file/file_path.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include "Version.h"
|
||||
|
||||
#include "core-log.h"
|
||||
#ifndef NO_LIBCO
|
||||
#include "libco.h"
|
||||
#endif
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
@@ -34,12 +42,28 @@
|
||||
#include "Display.h"
|
||||
#include "Prefs.h"
|
||||
|
||||
// Global variables
|
||||
C64 *TheC64 = NULL; // Global C64 object
|
||||
char AppDirPath[1024]; // Path of application directory
|
||||
/* Forward declarations */
|
||||
int init_graphics(void);
|
||||
|
||||
extern "C" {
|
||||
RFILE* rfopen(const char *path, const char *mode);
|
||||
int64_t rftell(RFILE* stream);
|
||||
int rfclose(RFILE* stream);
|
||||
int64_t rfread(void* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream);
|
||||
}
|
||||
#ifndef NO_LIBCO
|
||||
extern cothread_t mainThread;
|
||||
extern cothread_t emuThread;
|
||||
#endif
|
||||
|
||||
// ROM file names
|
||||
/* Global variables */
|
||||
C64 *TheC64 = NULL; /* Global C64 object */
|
||||
char AppDirPath[1024]; /* Path of application directory */
|
||||
char Frodo::device_path[256] = "";
|
||||
Frodo *the_app;
|
||||
|
||||
/* ROM file names */
|
||||
#ifndef DATADIR
|
||||
#define DATADIR
|
||||
#endif
|
||||
@@ -49,25 +73,22 @@ char AppDirPath[1024]; // Path of application directory
|
||||
#define CHAR_ROM_FILE DATADIR "Char ROM"
|
||||
#define DRIVE_ROM_FILE DATADIR "1541 ROM"
|
||||
|
||||
|
||||
// Builtin ROMs
|
||||
/* Builtin ROMs */
|
||||
#include "Basic_ROM.h"
|
||||
#include "Kernal_ROM.h"
|
||||
#include "Char_ROM.h"
|
||||
#include "1541_ROM.h"
|
||||
|
||||
/*
|
||||
* Load C64 ROM files
|
||||
*/
|
||||
/* Load C64 ROM files */
|
||||
|
||||
bool Frodo::load_rom(const char *which, const char *path,
|
||||
uint8 *where, size_t size, const uint8 *builtin)
|
||||
{
|
||||
FILE *f = fopen(path, "rb");
|
||||
RFILE *f = rfopen(path, "rb");
|
||||
if (f)
|
||||
{
|
||||
size_t actual = fread(where, 1, size, f);
|
||||
fclose(f);
|
||||
size_t actual = (size_t)rfread(where, 1, size, f);
|
||||
rfclose(f);
|
||||
if (actual == size)
|
||||
return true;
|
||||
}
|
||||
@@ -93,26 +114,6 @@ void Frodo::load_rom_files()
|
||||
memcpy(TheC64->ROM1541, builtin_drive_rom, DRIVE_ROM_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* main_x.i - Main program, X specific stuff
|
||||
*
|
||||
* Frodo (C) 1994-1997,2002 Christian Bauer
|
||||
*/
|
||||
|
||||
#include "Version.h"
|
||||
|
||||
#include "core-log.h"
|
||||
#ifndef NO_LIBCO
|
||||
#include "libco.h"
|
||||
extern cothread_t mainThread;
|
||||
extern cothread_t emuThread;
|
||||
#endif
|
||||
|
||||
extern int init_graphics(void);
|
||||
|
||||
Frodo *the_app;
|
||||
|
||||
char Frodo::device_path[256] = "";
|
||||
|
||||
/*
|
||||
* Create application object and start it
|
||||
@@ -154,20 +155,14 @@ Frodo::Frodo()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process command line arguments
|
||||
*/
|
||||
|
||||
/* Process command line arguments */
|
||||
void Frodo::ArgvReceived(int argc, char **argv)
|
||||
{
|
||||
if (argc == 2)
|
||||
strncpy(device_path, argv[1], 255);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments processed, run emulation
|
||||
*/
|
||||
|
||||
/* Arguments processed, run emulation */
|
||||
void Frodo::ReadyToRun(void)
|
||||
{
|
||||
#if defined (__vita__) || defined(__psp__)
|
||||
@@ -194,12 +189,9 @@ void Frodo::ReadyToRun(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether path name refers to a directory
|
||||
*/
|
||||
/* Determine whether path name refers to a directory */
|
||||
|
||||
bool IsDirectory(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
|
||||
return path_is_directory(path);
|
||||
}
|
||||
+23
-151
@@ -23,20 +23,24 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <file/file_path.h>
|
||||
#include <streams/file_stream.h>
|
||||
|
||||
#include "utype.h"
|
||||
|
||||
#if defined(WIN32) && !defined(_VCWIN_)
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "dialog.h"
|
||||
#include "file.h"
|
||||
#include "zip.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#define ftello ftell
|
||||
#endif
|
||||
/* Forward declarations */
|
||||
extern "C" {
|
||||
RFILE* rfopen(const char *path, const char *mode);
|
||||
int64_t rfseek(RFILE* stream, int64_t offset, int origin);
|
||||
int64_t rftell(RFILE* stream);
|
||||
int rfclose(RFILE* stream);
|
||||
int64_t rfread(void* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
@@ -100,7 +104,7 @@ static bool File_IsRootFileName(const char *pszFileName)
|
||||
if (pszFileName[0] == PATHSEP)
|
||||
return true;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
if (pszFileName[1] == ':')
|
||||
return true;
|
||||
#endif
|
||||
@@ -172,10 +176,9 @@ Uint8 *File_Read(const char *pszFileName, long *pFileSize, const char * const pp
|
||||
/* Is it a gzipped file? */
|
||||
if (File_DoesFileExtensionMatch(filepath, ".gz"))
|
||||
{
|
||||
gzFile hGzFile;
|
||||
/* Open and read gzipped file */
|
||||
hGzFile = gzopen(filepath, "rb");
|
||||
if (hGzFile != NULL)
|
||||
gzFile hGzFile = gzopen(filepath, "rb");
|
||||
if (hGzFile)
|
||||
{
|
||||
/* Find size of file: */
|
||||
do
|
||||
@@ -203,21 +206,19 @@ Uint8 *File_Read(const char *pszFileName, long *pFileSize, const char * const pp
|
||||
}
|
||||
else /* It is a normal file */
|
||||
{
|
||||
FILE *hDiskFile;
|
||||
/* Open and read normal file */
|
||||
hDiskFile = fopen(filepath, "rb");
|
||||
if (hDiskFile != NULL)
|
||||
RFILE *hDiskFile = rfopen(filepath, "rb");
|
||||
if (hDiskFile)
|
||||
{
|
||||
/* Find size of file: */
|
||||
fseek(hDiskFile, 0, SEEK_END);
|
||||
FileSize = ftell(hDiskFile);
|
||||
fseek(hDiskFile, 0, SEEK_SET);
|
||||
rfseek(hDiskFile, 0, SEEK_END);
|
||||
FileSize = rftell(hDiskFile);
|
||||
rfseek(hDiskFile, 0, SEEK_SET);
|
||||
/* Read in... */
|
||||
pFile = (Uint8*)malloc(FileSize);
|
||||
if (pFile)
|
||||
FileSize = fread(pFile, 1, FileSize, hDiskFile);
|
||||
|
||||
fclose(hDiskFile);
|
||||
FileSize = rfread(pFile, 1, FileSize, hDiskFile);
|
||||
rfclose(hDiskFile);
|
||||
}
|
||||
}
|
||||
free(filepath);
|
||||
@@ -229,79 +230,6 @@ Uint8 *File_Read(const char *pszFileName, long *pFileSize, const char * const pp
|
||||
return pFile; /* Return to where read in/allocated */
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Save file to disk, return FALSE if errors
|
||||
*/
|
||||
bool File_Save(const char *pszFileName, const Uint8 *pAddress, size_t Size, bool bQueryOverwrite)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
/* Check if need to ask user if to overwrite */
|
||||
if (bQueryOverwrite)
|
||||
{
|
||||
/* If file exists, ask if OK to overwrite */
|
||||
if (!File_QueryOverwrite(pszFileName))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Normal file or gzipped file? */
|
||||
if (File_DoesFileExtensionMatch(pszFileName, ".gz"))
|
||||
{
|
||||
gzFile hGzFile;
|
||||
/* Create a gzipped file: */
|
||||
hGzFile = gzopen(pszFileName, "wb");
|
||||
if (hGzFile != NULL)
|
||||
{
|
||||
/* Write data, set success flag */
|
||||
if (gzwrite(hGzFile, pAddress, Size) == (int)Size)
|
||||
bRet = true;
|
||||
|
||||
gzclose(hGzFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE *hDiskFile;
|
||||
/* Create a normal file: */
|
||||
hDiskFile = fopen(pszFileName, "wb");
|
||||
if (hDiskFile != NULL)
|
||||
{
|
||||
/* Write data, set success flag */
|
||||
if (fwrite(pAddress, 1, Size, hDiskFile) == Size)
|
||||
bRet = true;
|
||||
|
||||
fclose(hDiskFile);
|
||||
}
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Return size of file, -1 if error
|
||||
*/
|
||||
off_t File_Length(const char *pszFileName)
|
||||
{
|
||||
off_t FileSize;
|
||||
FILE *hDiskFile = fopen(pszFileName, "rb");
|
||||
|
||||
if (hDiskFile!=NULL)
|
||||
{
|
||||
fseek(hDiskFile, 0, SEEK_END);
|
||||
FileSize = ftello(hDiskFile);
|
||||
fseek(hDiskFile, 0, SEEK_SET);
|
||||
fclose(hDiskFile);
|
||||
return FileSize;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Return TRUE if file exists, is readable or writable at least and is not
|
||||
@@ -309,58 +237,18 @@ off_t File_Length(const char *pszFileName)
|
||||
*/
|
||||
bool File_Exists(const char *filename)
|
||||
{
|
||||
#ifdef RETRO
|
||||
if( access( filename, F_OK ) != -1 )
|
||||
return true;
|
||||
return false;
|
||||
#else
|
||||
struct stat buf;
|
||||
if ( stat(filename, &buf) == 0
|
||||
&& (buf.st_mode & (S_IRUSR|S_IWUSR))
|
||||
&& !(buf.st_mode & S_IFDIR))
|
||||
{
|
||||
/* file points to user readable regular file */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
return path_is_valid(filename);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Return TRUE if directory exists.
|
||||
*/
|
||||
bool File_DirExists(const char *path)
|
||||
{
|
||||
struct stat buf;
|
||||
return (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode));
|
||||
return path_is_directory(path);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Find if file exists, and if so ask user if OK to overwrite
|
||||
*/
|
||||
bool File_QueryOverwrite(const char *pszFileName)
|
||||
{
|
||||
const char *fmt = NULL;
|
||||
char *szString = NULL;
|
||||
bool ret = true;
|
||||
|
||||
/* Try and find if file exists */
|
||||
if (File_Exists(pszFileName))
|
||||
{
|
||||
fmt = "File '%s' exists, overwrite?";
|
||||
/* File does exist, are we OK to overwrite? */
|
||||
szString = (char*)malloc(strlen(pszFileName) + strlen(fmt) + 1);
|
||||
sprintf(szString, fmt, pszFileName);
|
||||
ret = DlgAlert_Query(szString);
|
||||
free(szString);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Try filename with various extensions and check if file exists
|
||||
@@ -503,22 +391,6 @@ void File_ShrinkName(char *pDestFileName, const char *pSrcFileName, int maxlen)
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Wrapper for File_MakeAbsoluteName() which special-cases stdin/out/err
|
||||
* named files and empty file name. The given buffer should be opened
|
||||
* with File_Open() and closed with File_Close() if this function is used!
|
||||
* (On Linux one can use /dev/stdout etc, this is intended for other OSes)
|
||||
*/
|
||||
void File_MakeAbsoluteSpecialName(char *path)
|
||||
{
|
||||
if (path[0] &&
|
||||
strcmp(path, "stdin") != 0 &&
|
||||
strcmp(path, "stdout") != 0 &&
|
||||
strcmp(path, "stderr") != 0)
|
||||
File_MakeAbsoluteName(path);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Create a clean absolute file name from a (possibly) relative file name.
|
||||
|
||||
@@ -20,16 +20,12 @@ extern bool File_DoesFileExtensionMatch(const char *pszFileName, const char *psz
|
||||
extern const char *File_RemoveFileNameDrive(const char *pszFileName);
|
||||
extern bool File_DoesFileNameEndWithSlash(char *pszFileName);
|
||||
extern Uint8 *File_Read(const char *pszFileName, long *pFileSize, const char * const ppszExts[]);
|
||||
extern bool File_Save(const char *pszFileName, const Uint8 *pAddress, size_t Size, bool bQueryOverwrite);
|
||||
extern off_t File_Length(const char *pszFileName);
|
||||
extern bool File_Exists(const char *pszFileName);
|
||||
extern bool File_DirExists(const char *psDirName);
|
||||
extern bool File_QueryOverwrite(const char *pszFileName);
|
||||
extern char* File_FindPossibleExtFileName(const char *pszFileName,const char * const ppszExts[]);
|
||||
extern void File_SplitPath(const char *pSrcFileName, char *pDir, char *pName, char *Ext);
|
||||
extern char* File_MakePath(const char *pDir, const char *pName, const char *pExt);
|
||||
extern void File_ShrinkName(char *pDestFileName, const char *pSrcFileName, int maxlen);
|
||||
extern void File_MakeAbsoluteSpecialName(char *pszFileName);
|
||||
extern void File_MakeAbsoluteName(char *pszFileName);
|
||||
extern void File_MakeValidPathName(char *pPathName);
|
||||
extern void File_PathShorten(char *path, int dirs);
|
||||
|
||||
Reference in new issue
Block a user