163 lines
5.6 KiB
C
163 lines
5.6 KiB
C
|
/*
|
||
|
gcr.h - Group Code Recording helper functions
|
||
|
|
||
|
(C) 2001-05 Markus Brenner <markus(at)brenner(dot)de>
|
||
|
and Pete Rittwage <peter(at)rittwage(dot)com>
|
||
|
based on code by Andreas Boose
|
||
|
|
||
|
V 0.33 improved sector extraction, added find_track_cycle() function
|
||
|
V 0.34 added MAX_SYNC_OFFSET constant, approximated to 800 GCR bytes
|
||
|
V 0.35 modified find_track_cycle() interface
|
||
|
V 0.36 added bad GCR code detection
|
||
|
V 0.36a added find_sector_gap(), find_sector0(), extract_GCR_track()
|
||
|
V 0.36d Untold number of additions and consequent bugfixes. (pjr)
|
||
|
|
||
|
*/
|
||
|
|
||
|
#ifndef _GCR_
|
||
|
#define _GCR_
|
||
|
|
||
|
#include "integer.h" /* Basic integer types */
|
||
|
|
||
|
//#define BYTE unsigned char
|
||
|
//#define DWORD unsigned int
|
||
|
#define MAX_TRACKS_1541 42
|
||
|
#define MAX_TRACKS_1571 (MAX_TRACKS_1541 * 2)
|
||
|
#define MAX_HALFTRACKS_1541 (MAX_TRACKS_1541 * 2)
|
||
|
#define MAX_HALFTRACKS_1571 (MAX_TRACKS_1571 * 2)
|
||
|
|
||
|
/* D64 constants */
|
||
|
#define BLOCKSONDISK 683
|
||
|
#define BLOCKSEXTRA 85
|
||
|
#define MAXBLOCKSONDISK (BLOCKSONDISK+BLOCKSEXTRA)
|
||
|
#define MAX_TRACK_D64 40
|
||
|
|
||
|
/* G64 constants (only needed for current VICE support */
|
||
|
#define G64_TRACK_MAXLEN 7928
|
||
|
#define G64_TRACK_LENGTH (G64_TRACK_MAXLEN+2)
|
||
|
|
||
|
/* NIB format constants */
|
||
|
#define NIB_TRACK_LENGTH 0x2000
|
||
|
#define NIB_HEADER_SIZE 0xFF
|
||
|
|
||
|
/*
|
||
|
number of GCR bytes until NO SYNC error
|
||
|
timer counts down from $d000 to $8000 (20480 cycles)
|
||
|
until timeout when waiting for a SYNC signal
|
||
|
This is approx. 20.48 ms, which is approx 1/10th disk revolution
|
||
|
8000 GCR bytes / 10 = 800 bytes
|
||
|
*/
|
||
|
//#define MAX_SYNC_OFFSET 800
|
||
|
/* this was too small for Lode Runner original (805), so increase to 820 */
|
||
|
//#define MAX_SYNC_OFFSET 820
|
||
|
#define MAX_SYNC_OFFSET 0x1500
|
||
|
|
||
|
#define SIGNIFICANT_GAPLEN_DIFF 0x20
|
||
|
|
||
|
#define GCR_BLOCK_HEADER_LEN 24
|
||
|
#define GCR_BLOCK_DATA_LEN 337
|
||
|
#define GCR_BLOCK_LEN (GCR_BLOCK_HEADER_LEN + GCR_BLOCK_DATA_LEN)
|
||
|
|
||
|
/* To calculate the bytes per rotation:
|
||
|
|
||
|
4,000,000 * 60
|
||
|
b/minute = ------------------------------------------------ = x bytes/minute
|
||
|
speed_zone_divisor * 8bits
|
||
|
|
||
|
4,000,000 is the base clock frequency divided by 4.
|
||
|
8 is the number of bits per byte.
|
||
|
60 gets us to a minute of data, which we can then divide by RPM to
|
||
|
get our numbers.
|
||
|
|
||
|
speed zone divisors are 13, 14, 15, 16 for densities 3, 2, 1, 0 respectively
|
||
|
*/
|
||
|
|
||
|
#define DENSITY3 2307692.308 // bytes per minute
|
||
|
#define DENSITY2 2142857.143
|
||
|
#define DENSITY1 2000000.000
|
||
|
#define DENSITY0 1875000.000
|
||
|
|
||
|
/* Some disks have much less data than we normally expect to be able to write at a given density.
|
||
|
It's like short tracks, but it's a mastering issue not a protection.
|
||
|
This keeps us from getting errors in the track cycle detection */
|
||
|
#define CAP_MIN_ALLOWANCE 150
|
||
|
|
||
|
/* minimum amount of good sequential GCR for formatted track */
|
||
|
#define GCR_MIN_FORMATTED 64 // chessmaster track 29 is shortest so far
|
||
|
|
||
|
/* Disk Controller error codes */
|
||
|
#define SECTOR_OK 0x01
|
||
|
#define HEADER_NOT_FOUND 0x02
|
||
|
#define SYNC_NOT_FOUND 0x03
|
||
|
#define DATA_NOT_FOUND 0x04
|
||
|
#define BAD_DATA_CHECKSUM 0x05
|
||
|
#define BAD_GCR_CODE 0x06
|
||
|
#define VERIFY_ERROR 0x07
|
||
|
#define WRITE_PROTECTED 0x08
|
||
|
#define BAD_HEADER_CHECKSUM 0x09
|
||
|
#define ID_MISMATCH 0x0b
|
||
|
#define DISK_NOT_INSERTED 0x0f
|
||
|
|
||
|
#define BM_MATCH 0x10
|
||
|
#define BM_NO_CYCLE 0x20
|
||
|
#define BM_NO_SYNC 0x40
|
||
|
#define BM_FF_TRACK 0x80
|
||
|
|
||
|
#define ALIGN_NONE 0
|
||
|
#define ALIGN_GAP 1
|
||
|
#define ALIGN_SEC0 2
|
||
|
#define ALIGN_LONGSYNC 3
|
||
|
#define ALIGN_WEAK 4
|
||
|
#define ALIGN_VMAX 5
|
||
|
#define ALIGN_AUTOGAP 6
|
||
|
|
||
|
#define GCR_MASK_BAD_FIRST 0
|
||
|
#define GCR_MASK_BAD_LAST 1
|
||
|
|
||
|
/* global variables */
|
||
|
extern char sector_map_1541[];
|
||
|
extern BYTE speed_map_1541[];
|
||
|
extern int capacity[];
|
||
|
extern int capacity_min[];
|
||
|
extern int capacity_max[];\
|
||
|
extern int gap_match_length;
|
||
|
|
||
|
/* prototypes */
|
||
|
int find_sync(BYTE ** gcr_pptr, BYTE * gcr_end);
|
||
|
void convert_4bytes_to_GCR(BYTE * buffer, BYTE * ptr);
|
||
|
int convert_4bytes_from_GCR(BYTE * gcr, BYTE * plain);
|
||
|
int extract_id(BYTE * gcr_track, BYTE * id);
|
||
|
int extract_cosmetic_id(BYTE * gcr_track, BYTE * id);
|
||
|
size_t find_track_cycle(BYTE ** cycle_start, BYTE ** cycle_stop, int cap_min,
|
||
|
int cap_max);
|
||
|
size_t find_nondos_track_cycle(BYTE ** cycle_start, BYTE ** cycle_stop,
|
||
|
int cap_min, int cap_max);
|
||
|
BYTE convert_GCR_sector(BYTE * gcr_start, BYTE * gcr_end,
|
||
|
BYTE * d64_sector, int track, int sector, BYTE * id);
|
||
|
void convert_sector_to_GCR(BYTE * buffer, BYTE * ptr,
|
||
|
int track, int sector, BYTE * diskID, int error);
|
||
|
BYTE * find_sector_gap(BYTE * work_buffer, int tracklen, size_t * p_sectorlen);
|
||
|
BYTE * find_sector0(BYTE * work_buffer, int tracklen, size_t * p_sectorlen);
|
||
|
int extract_GCR_track(BYTE * destination, BYTE * source, int * align,
|
||
|
int force_align, size_t cap_min, size_t cap_max);
|
||
|
int replace_bytes(BYTE * buffer, int length, BYTE srcbyte, BYTE dstbyte);
|
||
|
int check_bad_gcr(BYTE * gcrdata, int length, int fix);
|
||
|
int check_sync_flags(BYTE * gcrdata, int density, int length);
|
||
|
void bitshift(BYTE * gcrdata, int length, int bits);
|
||
|
int check_errors(BYTE * gcrdata, int length, int track, BYTE * id,
|
||
|
char * errorstring);
|
||
|
int check_empty(BYTE * gcrdata, int length, int track, BYTE * id,
|
||
|
char * errorstring);
|
||
|
int compare_tracks(BYTE * track1, BYTE * track2, int length1, int length2,
|
||
|
int same_disk, char * outputstring);
|
||
|
int compare_sectors(BYTE * track1, BYTE * track2, int length1, int length2,
|
||
|
BYTE * id1, BYTE * id2, int track, char * outputstring);
|
||
|
int strip_runs(BYTE * buffer, int length, int minrun, BYTE target);
|
||
|
int reduce_runs(BYTE * buffer, int length, int length_max, int minrun,
|
||
|
BYTE target);
|
||
|
int is_bad_gcr(BYTE * gcrdata, size_t length, size_t pos);
|
||
|
int check_formatted(BYTE * gcrdata);
|
||
|
int check_valid_data(BYTE * data, int length);
|
||
|
|
||
|
#endif
|