/*
 * disk/moochies.c
 *
 * Custom format as used on Moochies by Energize.
 *
 * Written in 2023 by Keith Krellwitz
 *
 * RAW TRACK LAYOUT:
 *  u32 0x44894489  :: Sync
 *  u16 0x5555  :: Padding
 *  u8 dat[6300]
 *
 * The calculated checksum is the sum of all raw words, but the 
 * checksum is not stored with the track. The checksum data is
 * stored at the end of track 1 on each disk. I copied the
 * checksum data to an array to verify the tracks.
 *
 * TRKTYP_moochies data layout:
 *  u8 sector_data[6300]
 *
 */

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

static const uint16_t crcs[];

static void *moochies_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[2], dat[ti->len];
        uint16_t sum;
        unsigned int i;
        char *block;

        if (s->word != 0x44894489)
            continue;

        if (stream_next_bits(s, 16) == -1)
            goto fail;
        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]);
            sum += (raw[0] << 8) | raw[1];
        }

        if (sum != crcs[tracknr] && sum != crcs[tracknr+160]) {
            /* The official IPF has different checksums for track 1 and 90 on disk 1*/
            if (tracknr != 1 && tracknr !=90)
                continue;
            else if ((tracknr == 1 && sum != 0xc5a5) || (tracknr == 90 && sum != 0x0372))
                continue;
        }

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

fail:
    return NULL;
}


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

    unsigned int i;

    tbuf_bits(tbuf, SPEED_AVG, bc_raw, 32, 0x44894489);
    tbuf_bits(tbuf, SPEED_AVG, bc_raw, 16, 0x5555);

    for (i = 0; i < ti->len; i++) {
        tbuf_bits(tbuf, SPEED_AVG, bc_mfm_even_odd, 8, dat[i]);
    }
    
}

struct track_handler moochies_handler = {
    .bytes_per_sector = 6300,
    .nr_sectors = 1,
    .write_raw = moochies_write_raw,
    .read_raw = moochies_read_raw
};

static const uint16_t crcs[] = {
    /* Disk 1 */
    0x0000, 0x7b17, 0xE546, 0xF86C, 0xA128, 0xBF2E, 0x530C, 0x5716,
    0x1C83, 0x58C6, 0x128A, 0x829D, 0x72AB, 0x2728, 0x1B7A, 0x4BD2,
    0x6834, 0x5285, 0x990F, 0x0D70, 0x6A53, 0x0FA7, 0xFDE0, 0x70AA,
    0x0570, 0xE1DD, 0x62F1, 0x6834, 0x14D9, 0x1C74, 0x1C26, 0x3A39,
    0xC68F, 0xFB98, 0x24BA, 0x85C9, 0x91B9, 0x526C, 0x5CCA, 0x8032,
    0x5944, 0xA693, 0xC219, 0x5469, 0xBC44, 0x0374, 0x1172, 0xCA57,
    0x2D33, 0xF84A, 0x115A, 0x0208, 0x8A0D, 0x72B1, 0x913C, 0x72DD,
    0x14B3, 0x6BB8, 0xB7E4, 0xAC9C, 0xA341, 0xBBD6, 0x5AEF, 0xC0AA,
    0xA427, 0x1EF7, 0x96B6, 0x16B2, 0x4565, 0x5E4D, 0x798E, 0x864B,
    0x442B, 0xB72C, 0x79BC, 0xA03C, 0x5253, 0xC5DB, 0xFDF4, 0xF9A9,
    0xC62E, 0x66FD, 0xA817, 0x1789, 0xEA8D, 0x5736, 0x06BD, 0xBF1F,
    0x13AE, 0xC8E4, 0x814E, 0xEF09, 0x4AF2, 0xE370, 0xEE6C, 0x1DFB,
    0x7512, 0x96C9, 0xAF5D, 0xA27E, 0x0931, 0xF72E, 0x25F2, 0x61F6,
    0xB0EC, 0xC865, 0xCCDF, 0xC8B4, 0x4444, 0x658B, 0x3FA7, 0xA506,
    0xBE91, 0xADF4, 0xB7BF, 0x3372, 0x5ED0, 0x96BB, 0x7E53, 0x8757,
    0x045D, 0xB4B0, 0x5FF3, 0xF3FE, 0x418F, 0x156E, 0x71F1, 0x1CD2,
    0x6B05, 0x44E3, 0x043F, 0x6D3A, 0x3340, 0xADBC, 0x016A, 0xD88A,
    0xE6CA, 0x5A14, 0x8C3A, 0x0980, 0x1A15, 0x16FD, 0xA19E, 0x92CE,
    0xEB9C, 0x2D78, 0xE841, 0xFAFE, 0xDE81, 0x7774, 0x425D, 0xC04D,
    0xB346, 0x240C, 0x0F65, 0xFE6D, 0x4759, 0x0735, 0xA6D9, 0x6E90,
    /* Disk 2 */
    0x0000, 0x133e, 0x210b, 0xa99a, 0x30cc, 0xbbfa, 0x8191, 0xecb1,
    0x8415, 0x5c27, 0x3b89, 0x74c2, 0x255b, 0x723b, 0x9c98, 0x4328,
    0x836e, 0x3aac, 0xb60a, 0xf4f7, 0xe907, 0xb37a, 0xf4e1, 0xb313,
    0x75c2, 0xab94, 0xbddc, 0x045d, 0x3912, 0x0df7, 0x2252, 0x7909,
    0x11c0, 0x436e, 0x3295, 0xff72, 0x1b37, 0xeb10, 0x621a, 0xed23,
    0x59e8, 0x4b2f, 0xc25d, 0xf617, 0x08ff, 0x9b93, 0x8f4f, 0x589f,
    0x92b5, 0xeb7e, 0x9b78, 0x93af, 0x4a15, 0x7f5f, 0x585b, 0x7f47,
    0xd8f0, 0x796f, 0x86b1, 0x5561, 0xdec0, 0x142f, 0x5750, 0x5e91,
    0xce3b, 0x06aa, 0x99f3, 0xed1d, 0x3694, 0x8a1d, 0x3437, 0xdb48,
    0x4ff8, 0x8bc4, 0x9b28, 0x74a8, 0xce33, 0xd79a, 0x701e, 0x987b,
    0x38cf, 0x6ce8, 0xbf4e, 0x59cd, 0x92cc, 0x3aa6, 0x47ea, 0x510a,
    0xbad3, 0xe30d, 0x979f, 0x5b82, 0xe6c2, 0xe210, 0x4981, 0x6f9a,
    0xeb94, 0xdc68, 0x9f26, 0x100d, 0x63ff, 0xaf01, 0x50b5, 0x334a,
    0xb91c, 0x72e3, 0x222a, 0xc0a5, 0xbadb, 0x5809, 0xbb54, 0x8946,
    0x74ea, 0x707a, 0xd0f4, 0x637b, 0x7534, 0x1ab6, 0x7eaa, 0xf520,
    0x908a, 0x4866, 0xbd1e, 0x3123, 0x1943, 0xe708, 0xb6ba, 0xed4c,
    0x145e, 0x98ee, 0xe73c, 0x6cca, 0xea4a, 0x7ceb, 0x725d, 0x336c,
    0xeb8a, 0x6cfa, 0x5fd3, 0x3de4, 0x8e17, 0x0999, 0x2570, 0x387c,
    0x4c64, 0x13da, 0xbbe5, 0xcdf7, 0xef3b, 0x6823, 0xb684, 0x8ee7,
    0x0181, 0xaa2a, 0x870e, 0x6e8d, 0xe943, 0x57fc, 0x807c, 0x807c
};

/*
 * Local variables:
 * mode: C
 * c-file-style: "Linux"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */
