static void *hellwig_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint32_t raw[2], dat[ti->bytes_per_sector/4], csum, sum; enum checksum_type checksum_type; unsigned int i, two_sync; char *block; if ((uint16_t)s->word != 0x4489) continue; ti->data_bitoff = s->index_offset_bc - 15; if (stream_next_bits(s, 16) == -1) goto fail; two_sync = (s->word == 0x44894489); if (two_sync && (stream_next_bits(s, 16) == -1)) goto fail; if (s->word != 0x44892aaa) continue; for (i = sum = 0; i < ARRAY_SIZE(dat); i++) { if (stream_next_bytes(s, raw, 8) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, raw, &dat[i]); sum += be32toh(dat[i]); } if (stream_next_bytes(s, raw, 8) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, raw, &csum); csum = be32toh(csum); if (csum == 0) { checksum_type = CSUM_zeroes; } else if (csum == 0xffffffff) { checksum_type = CSUM_ones; } else { checksum_type = CSUM_data; if (csum != sum) continue; } ti->len += 1; block = memalloc(ti->len); memcpy(block, dat, ti->len-1); block[ti->len-1] = checksum_type | ((two_sync?2:1) << 4); ti->total_bits = 102000; set_all_sectors_valid(ti); return block; } fail: return NULL; }
static void *firebird_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; uint16_t *block = memalloc(ti->len); while (stream_next_bit(s) != -1) { uint32_t idx_off = s->index_offset_bc - 31; uint8_t dat[2*(ti->len+2)]; if (s->word != 0x89448944) continue; stream_start_crc(s); if (stream_next_bits(s, 16) == -1) goto fail; if (s->word != 0x89448944) continue; if (ti->type == TRKTYP_firebird) { if (stream_next_bits(s, 16) == -1) goto fail; if (mfm_decode_word((uint16_t)s->word) != 0xff) continue; } else if (ti->type == TRKTYP_afterburner_data) { if (stream_next_bytes(s, dat, 6) == -1) goto fail; mfm_decode_bytes(bc_mfm, 3, dat, dat); if ((dat[0] != 0x41) || (dat[1] != 0x42) || (dat[2] != (tracknr/2))) continue; } if (stream_next_bytes(s, dat, sizeof(dat)) == -1) goto fail; if (s->crc16_ccitt != 0) continue; mfm_decode_bytes(bc_mfm, ti->len, dat, block); ti->data_bitoff = idx_off; if (ti->type == TRKTYP_ikplus) ti->data_bitoff -= 2*16; /* IK+ has a pre-sync header */ set_all_sectors_valid(ti); return block; } fail: free(block); return NULL; }
static void *back_future3_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint32_t raw[2], dat[ti->len/4], sum; unsigned int i; char *block; if ((uint16_t)s->word != 0x4489) continue; ti->data_bitoff = s->index_offset - 15; if (stream_next_bits(s, 32) == -1) goto fail; if (s->word != 0x552524a4) continue; if (stream_next_bits(s, 32) == -1) goto fail; if (s->word != 0x554a4945) continue; for (i = sum = 0; i < ti->len/4; i++) { if (stream_next_bytes(s, raw, 8) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, raw, &dat[i]); if ( i < ti->len/4 - 1) sum += be32toh(dat[i]); } /* Only verify the checksum on those tracks that are not * listed in the track_array*/ if (find_track(tracknr) == 0) if (sum != be32toh(dat[i-1])) continue; block = memalloc(ti->len); memcpy(block, dat, ti->len); set_all_sectors_valid(ti); return block; } fail: return NULL; }
static void *puffys_saga_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint16_t dat[2*2818], csum; unsigned int i; char *block; if (s->word != 0x44894489) continue; ti->data_bitoff = s->index_offset - 31; for (i = 0; i < 30; i++) { if (stream_next_bits(s, 32) == -1) goto fail; if (mfm_decode_bits(bc_mfm, s->word)) break; } if (i != 30) continue; if (stream_next_bits(s, 16) == -1) goto fail; if ((uint16_t)s->word != 0x4444) continue; if (stream_next_bytes(s, dat, sizeof(dat)) == -1) goto fail; mfm_decode_bytes(bc_mfm, sizeof(dat)/2, dat, dat); csum = 0; for (i = 1; i < 2818; i++) csum += be16toh(dat[i]); if ((be16toh(dat[0]) != csum) || (be16toh(dat[1]) != (tracknr/2))) continue; block = memalloc(ti->len); memcpy(block, &dat[2], ti->len); set_all_sectors_valid(ti); return block; } fail: return NULL; }
static void *sextett_protection_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; uint32_t *block; /* Tracks 159 & 161: no data, all same data_bitoff (==0) */ if (tracknr == 159) { /* Track 159 is only a protection track on Disk 1. */ struct track_info *t158 = &d->di->track[158]; return (t158->type == TRKTYP_sextett_protection) ? memalloc(0) : NULL; } else if (tracknr == 161) { /* Track 161: Protection on all disks. */ ti->total_bits &= ~15; return memalloc(0); } /* Disk 1, Track 158: find the key */ while (stream_next_bit(s) != -1) { if (s->word != 0x92459245) continue; ti->data_bitoff = s->index_offset_bc - 31; if (stream_next_bits(s, 32) == -1) break; block = memalloc(4); *block = htobe32(s->word); return block; } return NULL; }
static int check_sequence(struct stream *s, unsigned int nr, uint8_t byte) { while (--nr) { stream_next_bits(s, 16); if ((uint8_t)mfm_decode_word(s->word) != byte) break; } return !nr; }
static void *interceptor_software_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; char *ablk; unsigned int i; init_track_info(ti, TRKTYP_amigados); ablk = handlers[TRKTYP_amigados]->write_raw(d, tracknr, s); if ((ablk == NULL) || (ti->type != TRKTYP_amigados)) goto fail; stream_reset(s); while (stream_next_bit(s) != -1) { /* Sync word 0xa144 precedes the AmigaDOS block by ~2000 bits. */ if ((uint16_t)s->word != 0xa144) continue; ti->data_bitoff = s->index_offset_bc - 15; /* Check for a decent-length zero sequence after the sync. */ for (i = 0; i < 32; i++) if ((stream_next_bits(s, 32) == -1) || mfm_decode_word(s->word)) break; if (i != 32) continue; /* Skip 104400 bits after the sync pattern. Check for 0xa145 * fill pattern, repeating. */ stream_next_bits(s, 104400-32*32); if (s->word != 0xa145a145) continue; init_track_info(ti, TRKTYP_interceptor_software); ti->total_bits = 105550; return ablk; } fail: memfree(ablk); return NULL; }
static void *psygnosis_b_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; char *block = memalloc(ti->len); unsigned int j, k, nr_valid_blocks = 0; while ((stream_next_bit(s) != -1) && (nr_valid_blocks != ti->nr_sectors)) { uint16_t raw_dat[6*513]; uint32_t idx_off, new_valid = 0; if ((uint16_t)s->word != 0x4489) continue; idx_off = s->index_offset_bc - 15; if (stream_next_bits(s, 32) == -1) goto done; if (s->word != 0x552aaaaa) continue; for (j = 0; j < sizeof(raw_dat)/2; j++) { uint32_t dat; if (stream_next_bytes(s, &dat, 4) == -1) goto done; mfm_decode_bytes(bc_mfm_even_odd, 2, &dat, &raw_dat[j]); } for (j = 0; j < 6; j++) { uint16_t *sec = &raw_dat[j*513]; uint16_t csum = be16toh(*sec++), c = 0; for (k = 0; k < 512; k++) c += be16toh(sec[k]); if ((c == csum) && !is_valid_sector(ti, j)) { memcpy(&block[j*1024], sec, 1024); set_sector_valid(ti, j); nr_valid_blocks++; new_valid++; } } if (new_valid) ti->data_bitoff = idx_off; } done: if (nr_valid_blocks == 0) { free(block); return NULL; } return block; }
static void *phantom_fighter_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint16_t dat[0x1760], csum; unsigned int i; char *block; if (s->word != 0x44894489) continue; ti->data_bitoff = s->index_offset_bc - 31; if (stream_next_bits(s, 16) == -1) goto fail; for (i = 0; i < 8; i++) { if (stream_next_bytes(s, &dat[0x2ec*i], 0x2ec*2) == -1) goto fail; if (stream_next_bits(s, 32) == -1) goto fail; } mfm_decode_bytes(bc_mfm_even_odd, 0x1760, dat, dat); for (i = csum = 0; i < ti->len/2; i++) csum += be16toh(dat[i]); if (csum != be16toh(dat[ti->len/2])) continue; block = memalloc(ti->len); memcpy(block, dat, ti->len); set_all_sectors_valid(ti); return block; } fail: return NULL; }
static void *psygnosis_c_track0_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; uint16_t dat[V1_METABLK_WORDS+1], raw[2]; char *ablk, *block; unsigned int i, metablk_words, ver; init_track_info(ti, TRKTYP_amigados); ablk = handlers[TRKTYP_amigados]->write_raw(d, tracknr, s); if ((ablk == NULL) || (ti->type != TRKTYP_amigados)) goto fail; for (ver = 1; ver <= 2; ver++) { stream_reset(s); metablk_words = (ver == 1) ? V1_METABLK_WORDS : V2_METABLK_WORDS; while (stream_next_bit(s) != -1) { if ((uint16_t)s->word != 0x428a) continue; ti->data_bitoff = s->index_offset - 15; if ((ver == 2) && ((stream_next_bits(s, 16) == -1) || ((uint16_t)s->word != 0xaaaa))) continue; for (i = 0; i < (metablk_words + 1); i++) { if (stream_next_bytes(s, raw, 4) == -1) break; mfm_decode_bytes(bc_mfm_even_odd, 2, raw, &dat[i]); } if (checksum(&dat[1], metablk_words, ver) != be16toh(dat[0])) continue; init_track_info(ti, TRKTYP_psygnosis_c_track0); ti->len += metablk_words*2; ti->total_bits = 105500; block = memalloc(ti->len); memcpy(block, ablk, 512*11); memcpy(&block[512*11], &dat[1], metablk_words*2); memfree(ablk); return block; } } fail: memfree(ablk); return NULL; }
static void *rtype_a_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint8_t raw_dat[2*ti->len]; uint32_t csum; char *block; if ((uint16_t)s->word != 0x9521) continue; ti->data_bitoff = s->index_offset - 15; if (stream_next_bits(s, 16) == -1) goto fail; if (mfm_decode_bits(bc_mfm, (uint16_t)s->word) != 0) continue; if (stream_next_bits(s, 32) == -1) goto fail; csum = mfm_decode_bits(bc_mfm_odd, s->word); if (stream_next_bytes(s, raw_dat, 2*ti->len) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, ti->len, raw_dat, raw_dat); if (amigados_checksum(raw_dat, ti->len) != csum) continue; block = memalloc(ti->len); memcpy(block, raw_dat, ti->len); set_all_sectors_valid(ti); return block; } fail: return NULL; }
int stream_next_bytes(struct stream *s, void *p, unsigned int bytes) { unsigned int i; unsigned char *dat = p; for (i = 0; i < bytes; i++) { if (stream_next_bits(s, 8) == -1) return -1; dat[i] = (uint8_t)s->word; } return 0; }
static void *speedball_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint32_t dat[10000], track_len, csum; uint32_t idx_off = s->index_offset_bc - 31; unsigned int i; void *block; if (s->word != 0x44894489) continue; if (stream_next_bits(s, 32) == -1) goto fail; if (mfm_decode_word(s->word) != 0xfefe) continue; if (stream_next_bytes(s, dat, 3*8) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, &dat[0], &dat[0]); if (be32toh(dat[0]) != ID_THBB) continue; mfm_decode_bytes(bc_mfm_even_odd, 4, &dat[2], &dat[2]); track_len = be32toh(dat[2]); if (track_len != 5952) /* track length is always 5952 */ continue; mfm_decode_bytes(bc_mfm_even_odd, 4, &dat[4], &dat[4]); csum = be32toh(dat[4]); if (stream_next_bytes(s, dat, track_len*2) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, track_len, dat, dat); for (i = 0; i < track_len / 4; i++) csum ^= be32toh(dat[i]); if (csum != 0) continue; ti->data_bitoff = idx_off; set_all_sectors_valid(ti); ti->bytes_per_sector = ti->len = track_len; block = memalloc(ti->len); memcpy(block, dat, ti->len); return block; } fail: return NULL; }
static void *rtype_b_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { unsigned int i; uint32_t raw_dat[2*ti->len/4]; uint32_t csum = 0; char *block; if ((uint16_t)s->word != 0x9521) continue; ti->data_bitoff = s->index_offset - 15; if (stream_next_bits(s, 16) == -1) goto fail; if (mfm_decode_bits(bc_mfm, (uint16_t)s->word) != 0) continue; if (stream_next_bytes(s, raw_dat, 2*ti->len) == -1) goto fail; for (i = 0; i < ti->len/4; i++) mfm_decode_bytes(bc_mfm_even_odd, 4, &raw_dat[2*i], &raw_dat[i]); csum = amigados_checksum(raw_dat, ti->len); csum &= 0x55555555u; csum |= 0xaaaaaaaau; if (stream_next_bytes(s, &raw_dat[ti->len/4], 8) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, &raw_dat[ti->len/4], &raw_dat[ti->len/4]); if (csum != be32toh(raw_dat[ti->len/4])) continue; block = memalloc(ti->len); memcpy(block, raw_dat, ti->len); set_all_sectors_valid(ti); ti->total_bits = 105500; return block; } fail: return NULL; }
static void *firebird_b_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint32_t sync; uint8_t raw[2], dat[ti->len], sum; unsigned int i; char *block; sync = (ti->type == TRKTYP_quartz_a) ? 0x89448944 : 0x8944a92a; if (s->word != sync) continue; if (ti->type == TRKTYP_quartz_b) { if (stream_next_bits(s, 16) == -1) goto fail; if ((uint16_t)s->word != 0x8944) continue; ti->data_bitoff = s->index_offset_bc - 47; } else ti->data_bitoff = s->index_offset_bc - 31; for (i = sum = 0; i < ti->len; i++) { if (stream_next_bytes(s, raw, 2) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 1, raw, &dat[i]); } if (dat[2] != tracknr/2) continue; block = memalloc(ti->len); memcpy(block, dat, ti->len); set_all_sectors_valid(ti); ti->total_bits = 100500; return block; } fail: return NULL; }
static void *alienbreed_protection_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; uint32_t *dat = memalloc(3 * sizeof(uint32_t)); uint32_t x[2]; unsigned int i; while (stream_next_bit(s) != -1) { if (s->word != 0x89248924) continue; ti->data_bitoff = s->index_offset - 31; /* Get the data longs. */ for (i = 0; i < 3; i++) { stream_next_bytes(s, x, sizeof(x)); mfm_decode_bytes(bc_mfm_even_odd, 4, x, &dat[i]); } /* Check for a long sequence of zeroes */ for (i = 0; i < 1000; i++) { stream_next_bits(s, 32); if (mfm_decode_bits(bc_mfm, s->word) != 0) break; } if (i == 1000) goto found; } memfree(dat); return NULL; found: ti->len = 3 * sizeof(uint32_t); return dat; }
static void *arc_development_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint32_t raw[2], dat[12*512/4]; uint16_t csum, sum, craw[2]; unsigned int i, base; unsigned int sec; char *block; /* Both formats have at least one sync word. */ if ((uint16_t)s->word != 0x4489) continue; ti->data_bitoff = s->index_offset_bc - 15; if (s->word == 0x44894489) { /* Two sync words is format B. */ ti->type = TRKTYP_arc_development_b; ti->data_bitoff = s->index_offset_bc - 31; } else if (ti->type == TRKTYP_arc_development_b) { /* Format B must have two sync words. */ continue; } if (stream_next_bits(s, 32) == -1) goto fail; if (mfm_decode_bits(bc_mfm, s->word) != 0) continue; for (sec = base = 0; sec < ti->nr_sectors; sec++) { for (i = sum = 0; i < 512/4; i++) { if (stream_next_bytes(s, raw, 8) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, raw, &dat[i+base]); sum ^= (uint16_t)be32toh(dat[i+base]); } base += 512/4; if (stream_next_bytes(s, craw, 4) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 2, craw, &csum); if (sum != be16toh(csum)) goto fail; } /* Some releases use long tracks (for no good reason). */ stream_next_index(s); ti->total_bits = (s->track_len_bc > 107000) ? 111000 : (s->track_len_bc > 102000) ? 105500 : 100000; block = memalloc(ti->len); memcpy(block, dat, ti->len); set_all_sectors_valid(ti); return block; } fail: return NULL; }
static void *psygnosis_a_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; char *block; while (stream_next_bit(s) != -1) { uint32_t raw_dat[2*ti->len/4], hdr, csum; uint16_t sync = s->word; bool_t two_sync; if ((sync != 0x4489) && (sync != 0x4429)) continue; ti->data_bitoff = s->index_offset - 15; /* Check for second sync mark */ if (stream_next_bits(s, 16) == -1) goto fail; two_sync = ((uint16_t)s->word == sync); /* Read the track number and checksum. If there's no second sync mark, * the first 16 bits of the header info is already streamed. */ if (stream_next_bits(s, two_sync ? 32 : 16) == -1) goto fail; raw_dat[0] = htobe32(s->word); if (stream_next_bytes(s, &raw_dat[1], 12) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, &raw_dat[0], &hdr); mfm_decode_bytes(bc_mfm_even_odd, 4, &raw_dat[2], &csum); hdr = be32toh(hdr); csum = be32toh(csum); if (hdr != (0xffffff00u | tracknr)) continue; if (stream_next_bytes(s, raw_dat, sizeof(raw_dat)) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, ti->len, raw_dat, raw_dat); if (amigados_checksum(raw_dat, ti->len) != csum) continue; /* Some titles (Armourgeddon, Obitus...) mastered with long tracks. */ stream_next_index(s); if (s->track_bitlen > 103000) ti->total_bits = 105500; block = memalloc(ti->len + 4); *(uint16_t *)&block[ti->len] = htobe16(sync); *(uint16_t *)&block[ti->len+2] = two_sync ? htobe16(sync) : 0; memcpy(block, raw_dat, ti->len); set_all_sectors_valid(ti); ti->len += 4; /* for the sync marks */ return block; } fail: return NULL; }
static void *federation_of_free_traders_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; uint8_t *block = memalloc(ti->len); unsigned int i, nr_valid_blocks = 0, least_block = ~0u; while ((stream_next_bit(s) != -1) && (nr_valid_blocks != ti->nr_sectors)) { uint32_t idx_off = s->index_offset_bc - 31; uint16_t csum; uint8_t sec, *p; if (s->word != 0x44894489) continue; if (stream_next_bits(s, 32) == -1) goto done; if (mfm_decode_bits(bc_mfm, s->word) != (0xff00 | (tracknr^1))) continue; if (stream_next_bits(s, 16) == -1) goto done; sec = mfm_decode_bits(bc_mfm, (uint16_t)s->word); if ((sec >= ti->nr_sectors) || is_valid_sector(ti, sec)) continue; p = &block[sec * ti->bytes_per_sector]; for (i = csum = 0; i < ti->bytes_per_sector; i++) { if (stream_next_bits(s, 16) == -1) goto done; csum ^= (uint16_t)s->word; p[i] = mfm_decode_bits(bc_mfm, (uint16_t)s->word); } if (stream_next_bits(s, 32) == -1) goto done; if (csum != mfm_decode_bits(bc_mfm, s->word)) continue; set_sector_valid(ti, sec); nr_valid_blocks++; if (least_block > sec) { ti->data_bitoff = idx_off; least_block = sec; } } done: if (nr_valid_blocks == 0) { free(block); return NULL; } for (i = 0; i < ti->nr_sectors; i++) if (is_valid_sector(ti, i)) break; ti->data_bitoff -= i * 0xfc8; return block; }
static void *zoom_write_raw( struct disk *d, unsigned int tracknr, struct stream *s) { struct track_info *ti = &d->di->track[tracknr]; while (stream_next_bit(s) != -1) { uint32_t raw[2], dat[ti->len/4], csum; unsigned int i; char *block; if ((uint16_t)s->word != 0x4489) continue; /* Track 118 on the NTSC version only has * 2 sync words and the PAL version has * three.*/ if (s->word == 0xaaaa4489) { if (stream_next_bits(s, 16) == -1) goto fail; if ((uint16_t)s->word != 0x4489) continue; ti->data_bitoff = s->index_offset_bc - 31; if (ti->type == TRKTYP_zoom_b) { if (stream_next_bits(s, 16) == -1) goto fail; if ((uint16_t)s->word != 0x4489) continue; ti->data_bitoff = s->index_offset_bc - 47; } } else { if (stream_next_bits(s, 32) == -1) goto fail; if (s->word != 0x44894489) continue; ti->data_bitoff = s->index_offset_bc - 47; } for (i = 0; i < ti->len/4; i++) { if (stream_next_bytes(s, raw, 8) == -1) goto fail; mfm_decode_bytes(bc_mfm_even_odd, 4, raw, &dat[i]); } if((uint8_t)(0xff&be32toh(dat[0])) != (uint8_t)~(tracknr^~1)) continue; csum = 0; for (i = csum = 0; i < ti->len/4 - 5; i++) csum ^= be32toh(dat[i+2]); if (csum != be32toh(dat[1])) continue; block = memalloc(ti->len); memcpy(block, dat, ti->len); set_all_sectors_valid(ti); ti->total_bits = 102300; return block; } fail: return NULL; }