/*
 * disk/disposable_hero.c
 *
 * Custom format as used on Disposable Hero by Gremlin.
 *
 * Written in 2022 by Keith Krellwitz
 *
 * RAW TRACK LAYOUT:
 *  u16 0x4489 :: Sync
 *  u16 0x5555 :: Padding
 *  u16 dat[(768*8)/2+3]
 *
 * The are 3 words after 0x5555, but the loaders never does anything with
 * them and I did could not find any relevance of the data.  
 * 
 * No checksum found.  Added a checksum check to validate the tracks
 * 
 * 
 * TRKTYP_disposable_hero data layout:
 *  u8 sector_data[0x1800]
 */


#include <libdisk/util.h>
#include <private/disk.h>

static const uint16_t crcs[];

/* KAF: This is the track data len corresponding to the CRC table. */
#define track_data_len ((768+3)*8)

static void *disposable_hero_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 raw[8], dat[track_data_len/2];
        unsigned int i;
        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;
        if ((uint16_t)s->word != 0x5555)
            continue;

        stream_start_crc(s);
        for (i = 0; i < 768+3; i++) {
            if (stream_next_bytes(s, raw, 2*8) == -1)
                break;
            mfm_decode_bytes(bc_mfm_even_odd, 8, raw, &dat[i*4]);
        }

        if (s->crc16_ccitt != crcs[tracknr] && s->crc16_ccitt != crcs[tracknr+160])
            goto fail;

        stream_next_index(s);
        ti->total_bits = s->track_len_bc;
        ti->len = track_data_len;
        block = memalloc(ti->len);
        memcpy(block, dat, ti->len);
        set_all_sectors_valid(ti);
        return block;
    }

fail:
    return NULL;
}

static void disposable_hero_read_raw(
    struct disk *d, unsigned int tracknr, struct tbuf *tbuf)
{
    struct track_info *ti = &d->di->track[tracknr];
    uint16_t *dat = (uint16_t *)ti->dat;
    unsigned int i;

    tbuf_bits(tbuf, SPEED_AVG, bc_raw, 16, 0x4489);
    tbuf_bits(tbuf, SPEED_AVG, bc_raw, 16, 0x5555);

    for (i = 0; i < 768+3; i++) {
        tbuf_bytes(tbuf, SPEED_AVG, bc_mfm_even_odd, 8, &dat[i*4]);
    }
}

struct track_handler disposable_hero_handler = {
    .bytes_per_sector = 768,
    .nr_sectors = 8,
    .write_raw = disposable_hero_write_raw,
    .read_raw = disposable_hero_read_raw
};

static const uint16_t crcs[] = {
    /* Disk 1 */
    0x0000, 0x2190, 0x824c, 0x05ec, 0xb426, 0xf9bb, 0x630f, 0x6433,
    0x1b07, 0x9db5, 0x03f8, 0x7457, 0x6357, 0x8588, 0x1016, 0x9a19,
    0xc67a, 0x252c, 0x6f0f, 0xda25, 0x6dd9, 0xb8f7, 0xa2b8, 0xd4f2,
    0x84ba, 0xc49f, 0x86e6, 0x7f6b, 0x99a4, 0x74f6, 0xb3bb, 0x0bc1,
    0x187d, 0xcc10, 0x9015, 0x58db, 0x65e6, 0xf3f4, 0x2eaa, 0x004e,
    0xf395, 0xc8d6, 0x37f7, 0xc312, 0xa685, 0x84c7, 0x502c, 0xf79d,
    0x5d67, 0x9181, 0xfad4, 0xbc06, 0x3bc4, 0x6261, 0x1fbd, 0x30e4,
    0x4373, 0x69d8, 0xfbcb, 0xee46, 0x5c7d, 0x217d, 0xcc14, 0xb63b,
    0x1e61, 0x365a, 0x937d, 0x61bb, 0x6acf, 0xefa4, 0xbddb, 0xa9af,
    0x0da9, 0xc9fd, 0xd453, 0x50fa, 0x6005, 0x4d7b, 0xba4a, 0x423c,
    0x3b57, 0x92af, 0x6b29, 0x067c, 0xabe2, 0x3792, 0x2937, 0xbed7,
    0xf9e2, 0x5e9d, 0xe797, 0xca90, 0xe45b, 0x1fcc, 0x3e45, 0x810b,
    0x0783, 0xfebc, 0x24cf, 0xd25a, 0x6a2b, 0xa1c7, 0x8667, 0x9a2b,
    0x6af0, 0x0091, 0xe5cf, 0x1808, 0x7c6a, 0x7512, 0x01c7, 0x386f,
    0xbabb, 0xa694, 0x5cd7, 0x6778, 0x18bf, 0xfebe, 0xfc8e, 0x8f0b,
    0xd5a6, 0x84fe, 0x5a1f, 0x35f3, 0x4647, 0x6d04, 0x6ca9, 0xa5a5,
    0x35a7, 0x4c1f, 0xa5f3, 0xdb85, 0x3d50, 0xd628, 0x862e, 0x44e9,
    0xa104, 0xb5f8, 0x86f4, 0xba3f, 0x4958, 0xa689, 0x00bf, 0x3f6e,
    0xc14d, 0x7496, 0x29f6, 0xfd3b, 0x58be, 0xbce2, 0x1550, 0x02b6,
    0x66e1, 0x55bd, 0x2e01, 0x2f42, 0x71c5, 0x4ac5, 0x66b5, 0xd6bd,
    /* Disk 2 */
    0x5fc0, 0x78e9, 0x0bca, 0xd47d, 0x454d, 0x5dce, 0xd277, 0xf2f8,
    0xcf3a, 0xba9f, 0xe0a3, 0xa8b6, 0x9315, 0x3bb2, 0xaea0, 0x130e,
    0x7cc2, 0x1c11, 0x893b, 0x5cc0, 0x0b23, 0xa94e, 0xda6f, 0x0171,
    0xf483, 0x2b12, 0x5993, 0x2de5, 0xb392, 0xfcbd, 0x692d, 0x0334,
    0x0697, 0x8ab6, 0x4716, 0xb924, 0x1227, 0x1a50, 0x5d39, 0x4112,
    0xfd8e, 0x5931, 0x934d, 0x2afc, 0x0ade, 0xbea9, 0x8de6, 0x897c,
    0xc4bf, 0x39f0, 0xb7c8, 0x09a6, 0x5f52, 0x5499, 0x24d4, 0x0d83,
    0xf55b, 0x4a9a, 0x3b37, 0xc363, 0x57ad, 0x3a47, 0x633a, 0xe6b7,
    0x7fc9, 0x23c9, 0x1b4f, 0xca89, 0x56b1, 0x14b8, 0x9e53, 0xad0f,
    0x3549, 0x7500, 0x89dc, 0xf6a7, 0x893d, 0xa069, 0x8425, 0x46b1,
    0x048a, 0x72a4, 0x892f, 0x3eae, 0x9403, 0xf801, 0x2403, 0x063c,
    0x3de5, 0x40e6, 0xcb4a, 0x29d2, 0xa50d, 0xe957, 0x12e8, 0x08f6,
    0x00c8, 0xd42c, 0x9fbb, 0x9034, 0x31c3, 0x1e8a, 0x1afe, 0xa6dc,
    0x90e4, 0xf9de, 0x88cc, 0x1d3a, 0xff1d, 0x3d38, 0xfba5, 0x1e7a,
    0x28b2, 0xa7ed, 0x8f67, 0xc596, 0x7f9f, 0xe050, 0x63cd, 0xba31,
    0xa4a0, 0x4b51, 0x6bd5, 0x3302, 0x5aed, 0xe6e0, 0xcf2f, 0x76d5,
    0x1d17, 0x4923, 0x14a5, 0x783f, 0xf735, 0x02d5, 0xf4ec, 0xc1fe,
    0xc1dd, 0x3386, 0x7971, 0x2f22, 0xbc10, 0x0d0e, 0x0c50, 0xe02b,
    0x9169, 0xe1f4, 0x3d76, 0x585d, 0x2876, 0x964e, 0xa231, 0x72ba,
    0x9ac5, 0x7d99, 0xb0d9, 0x7eb7, 0x1675, 0xa7c2, 0xdca0, 0xc764
};
/*
 * Local variables:
 * mode: C
 * c-file-style: "Linux"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */

