1
0
mirror of https://git.code.sf.net/p/fuse-emulator/fuse synced 2026-01-28 14:20:54 +03:00
Files
fuse/peripherals/disk/trdos.c
2016-10-24 11:45:18 +11:00

141 lines
3.9 KiB
C

/* trdos.c: Routines for handling the TR-DOS filesystem
Copyright (c) 2016 Sergio Baldoví
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
E-mail: serbalgi@gmail.com
*/
#include <config.h>
#include <string.h>
#include "trdos.h"
int
trdos_read_spec( trdos_spec_t *spec, const libspectrum_byte *src )
{
if( *src ) return -1;
spec->first_free_sector = src[225];
spec->first_free_track = src[226];
spec->disk_type = src[227];
spec->file_count = src[228];
spec->free_sectors = src[229] + src[230] * 0x100;
spec->id = src[231];
if( spec->id != 16 ) return -1;
memcpy( spec->password, src + 234, 9 );
spec->deleted_files = src[244];
memcpy( spec->disk_label, src + 245, 8 );
return 0;
}
void
trdos_write_spec( libspectrum_byte *dest, const trdos_spec_t *spec )
{
memset( dest, 0, 256 );
dest[225] = spec->first_free_sector;
dest[226] = spec->first_free_track;
dest[227] = spec->disk_type;
dest[228] = spec->file_count;
dest[229] = spec->free_sectors & 0xff;
dest[230] = spec->free_sectors >> 8;
dest[231] = spec->id;
memcpy( dest + 234, spec->password, 9 );
dest[244] = spec->deleted_files;
memcpy( dest + 245, spec->disk_label, 8 );
}
int
trdos_read_dirent( trdos_dirent_t *entry, const libspectrum_byte *src )
{
memcpy( entry->filename, src, 8 );
entry->file_extension = src[8];
entry->param1 = src[9] + src[10] * 0x100;
entry->param2 = src[11] + src[12] * 0x100;
entry->file_length = src[13];
entry->start_sector = src[14];
entry->start_track = src[15];
return entry->filename[0]? 0 : 1;
}
void
trdos_write_dirent( libspectrum_byte *dest, const trdos_dirent_t *entry )
{
memcpy( dest, entry->filename, 8 );
dest[8] = entry->file_extension;
dest[9] = entry->param1 & 0xff;
dest[10] = entry->param1 >> 8;
dest[11] = entry->param2 & 0xff;
dest[12] = entry->param2 >> 8;
dest[13] = entry->file_length;
dest[14] = entry->start_sector;
dest[15] = entry->start_track;
}
int
trdos_read_fat( trdos_boot_info_t *info, const libspectrum_byte *sectors,
unsigned int seclen )
{
int i, j, error;
trdos_dirent_t entry;
const libspectrum_byte *sector;
info->have_boot_file = 0;
info->basic_files_count = 0;
/* FAT sectors */
for( i = 0; i < 8; i++ ) {
sector = sectors + i * seclen * 2; /* interleaved */
/* Note: some TR-DOS versions like 5.04T have a turbo format with
sequential sectors: 1, 2, 3, ..., 8, 9, 10, ...
The SCL/TRD image formats can't specify a format mode and Fuse
load the sectors as interleaved: 1, 9, 2, 10, 3, ...
*/
/* FAT entries */
for( j = 0; j < 16; j++ ) {
error = trdos_read_dirent( &entry, sector + j * 16 );
if( error ) return 0;
/* Basic files */
if( entry.filename[0] > 0x01 &&
entry.file_extension == 'B' ) {
/* Boot file */
if( !info->have_boot_file &&
!strncmp( (const char *)entry.filename, "boot ", 8 ) ) {
info->have_boot_file = 1;
}
/* First basic program */
if( info->basic_files_count == 0 ) {
memcpy( info->first_basic_file, entry.filename, 8 );
}
info->basic_files_count++;
}
}
}
return 0;
}