Skip to content

Commit

Permalink
v1.02 wip
Browse files Browse the repository at this point in the history
  • Loading branch information
r-lyeh committed Jul 15, 2024
1 parent b1c8844 commit 8daca50
Show file tree
Hide file tree
Showing 10 changed files with 372 additions and 187 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Code is highly experimental and prone to change in the future. I will keep alter
- [x] Kempston mouse. <!-- @todo: AMX mouse.-->
- [x] Kempston/Fuller/Cursor/Sinclair joysticks.
- [x] RF/CRT experience (not physically accurate though).
- [x] TAP/TZX/PZX/CSW tapes. Z80/SNA snaps. ROM/IF2 roms. <!-- @todo: tzx info on window title -->
- [x] TAP/TZX/PZX/CSW tapes. Z80/SNA snaps. ROM/IF2 roms.
- [x] DSK/EDSK/TRD/SCL/FDI/MGT/IMG/HOBETA disks.
- [x] SCR/PNG screenshots. <!-- @todo: ulaplus screenshots. video recording -->
- [x] ZIP/RAR/GZ archives.
Expand Down
55 changes: 41 additions & 14 deletions src/3rd_deflate.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ typedef uint32_t mz_uint;
#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
#define MZ_CLEAR_ARR(obj) memset((obj), 0, sizeof(obj))

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
#define MZ_READ_LE16(p) *((const uint16_t *)(p))
Expand Down Expand Up @@ -556,6 +557,9 @@ typedef enum
TDEFL_FINISH = 4
} tdefl_flush;

/* Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. */
typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);

// tdefl's compression state structure.
typedef struct
{
Expand All @@ -581,6 +585,10 @@ typedef struct
uint16_t m_next[TDEFL_LZ_DICT_SIZE];
uint16_t m_hash[TDEFL_LZ_HASH_SIZE];
uint8_t m_output_buf[TDEFL_OUT_BUF_SIZE];

tdefl_put_buf_func_ptr m_pPut_buf_func;
void *m_pPut_buf_user;

} tdefl_compressor;

// ------------------- zlib-style API's
Expand Down Expand Up @@ -1539,24 +1547,44 @@ tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, siz
return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
}

tdefl_status tdefl_init(tdefl_compressor *d, void *out, size_t outlen, int flags)
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
{
#if 0
d->m_putbuf_callback = putbuf_callback; d->m_pPut_buf_user = pPut_buf_user;
d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
d->m_pPut_buf_func = pPut_buf_func;
d->m_pPut_buf_user = pPut_buf_user;
d->m_flags = (mz_uint)(flags);
d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
MZ_CLEAR_ARR(d->m_hash);
d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
d->m_pLZ_flags = d->m_lz_code_buf;
*d->m_pLZ_flags = 0;
d->m_num_flags_left = 8;
d->m_pOutput_buf = d->m_output_buf;
d->m_pOutput_buf_end = d->m_output_buf;
d->m_prev_return_status = TDEFL_STATUS_OKAY;
d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
d->m_adler32 = 1;
d->m_pIn_buf = NULL;
d->m_pOut_buf = NULL;
d->m_pIn_buf_size = NULL;
d->m_pOut_buf_size = NULL;
d->m_flush = TDEFL_NO_FLUSH;
d->m_pSrc = NULL;
d->m_src_buf_left = 0;
d->m_out_buf_ofs = 0;
if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
MZ_CLEAR_ARR(d->m_dict);
memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
#else
return TDEFL_STATUS_OKAY;
}

tdefl_status tdefl_init_mem(tdefl_compressor *d, void *out, size_t outlen, int flags)
{
tdefl_compressor zero = {0};
*d = zero; // invalidated TDEFL_NONDETERMINISTIC_PARSING_FLAG option here

Expand All @@ -1570,7 +1598,6 @@ tdefl_status tdefl_init(tdefl_compressor *d, void *out, size_t outlen, int flags
d->m_flush = TDEFL_NO_FLUSH;
//memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
//memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
#endif
return TDEFL_STATUS_OKAY;
}

Expand All @@ -1591,7 +1618,7 @@ unsigned deflate_encode(const void *in, unsigned inlen, void *out, unsigned outl
mz_uint comp_flags = tdefl_num_probes[level % 12] | (level <= 3 ? TDEFL_GREEDY_PARSING_FLAG : 0);// | TDEFL_WRITE_ZLIB_HEADER );

tdefl_compressor *pComp = (tdefl_compressor*)MZ_REALLOC(0,sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
if(tdefl_init(pComp, out, outlen, (int)comp_flags) == TDEFL_STATUS_OKAY) {
if(tdefl_init_mem(pComp, out, outlen, (int)comp_flags) == TDEFL_STATUS_OKAY) {
if(tdefl_compress_buffer(pComp, in, inlen, TDEFL_FINISH) == TDEFL_STATUS_DONE) {
bytes = pComp->m_outbuffer[1] - pComp->m_outbuffer[0];
}
Expand Down
193 changes: 193 additions & 0 deletions src/3rd_zlib.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
#pragma once

#define deflate mz_deflate
#define deflateInit2 mz_deflateInit2
#define inflate mz_inflate
#define inflateInit2 mz_inflateInit2
#define z_stream mz_stream

#define Z_ADLER32_INIT MZ_ADLER32_INIT
#define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
#define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
#define Z_DEFLATED MZ_DEFLATED
#define Z_EMPTY MZ_EMPTY
#define Z_FINISH MZ_FINISH
#define Z_NO_FLUSH MZ_NO_FLUSH
#define Z_NULL MZ_NULL
#define Z_OK MZ_OK
#define Z_RLE MZ_RLE
#define Z_STREAM_END MZ_STREAM_END
#define Z_STREAM_ERROR MZ_STREAM_ERROR

#ifndef MINIZ_EXPORT
#define MINIZ_EXPORT
#endif
Expand Down Expand Up @@ -75,6 +94,30 @@ enum
MZ_PARAM_ERROR = -10000
};

enum
{
MZ_DEFAULT_STRATEGY = 0,
MZ_FILTERED = 1,
MZ_HUFFMAN_ONLY = 2,
MZ_RLE = 3,
MZ_FIXED = 4
};

/* Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. */
enum
{
MZ_NO_COMPRESSION = 0,
MZ_BEST_SPEED = 1,
MZ_BEST_COMPRESSION = 9,
MZ_UBER_COMPRESSION = 10,
MZ_DEFAULT_LEVEL = 6,
MZ_DEFAULT_COMPRESSION = -1
};

#define MZ_ADLER32_INIT 1
#define MZ_DEFLATED 8
#define MZ_DEFAULT_WINDOW_BITS 15

typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
typedef void (*mz_free_func)(void *opaque, void *address);
typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
Expand Down Expand Up @@ -370,3 +413,153 @@ int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char
{
return mz_uncompress2(pDest, pDest_len, pSource, &source_len);
}

// ----------------------------------------------------------------------------

static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };

mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
{
return d->m_adler32;
}

/* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
{
mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
if (window_bits > 0)
comp_flags |= TDEFL_WRITE_ZLIB_HEADER;

if (!level)
comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
else if (strategy == MZ_FILTERED)
comp_flags |= TDEFL_FILTER_MATCHES;
else if (strategy == MZ_HUFFMAN_ONLY)
comp_flags &= ~TDEFL_MAX_PROBES_MASK;
else if (strategy == MZ_FIXED)
comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
else if (strategy == MZ_RLE)
comp_flags |= TDEFL_RLE_MATCHES;

return comp_flags;
}

int mz_deflateInit(mz_streamp pStream, int level)
{
return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
}

int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
{
tdefl_compressor *pComp;
mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);

if (!pStream)
return MZ_STREAM_ERROR;
if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
return MZ_PARAM_ERROR;

pStream->data_type = 0;
pStream->adler = MZ_ADLER32_INIT;
pStream->msg = NULL;
pStream->reserved = 0;
pStream->total_in = 0;
pStream->total_out = 0;
if (!pStream->zalloc)
pStream->zalloc = miniz_def_alloc_func;
if (!pStream->zfree)
pStream->zfree = miniz_def_free_func;

pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
if (!pComp)
return MZ_MEM_ERROR;

pStream->state = (struct mz_internal_state *)pComp;

if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
{
mz_deflateEnd(pStream);
return MZ_PARAM_ERROR;
}

return MZ_OK;
}

int mz_deflateReset(mz_streamp pStream)
{
if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
return MZ_STREAM_ERROR;
pStream->total_in = pStream->total_out = 0;
tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
return MZ_OK;
}

int mz_deflate(mz_streamp pStream, int flush)
{
size_t in_bytes, out_bytes;
mz_ulong orig_total_in, orig_total_out;
int mz_status = MZ_OK;

if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
return MZ_STREAM_ERROR;
if (!pStream->avail_out)
return MZ_BUF_ERROR;

if (flush == MZ_PARTIAL_FLUSH)
flush = MZ_SYNC_FLUSH;

if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;

orig_total_in = pStream->total_in;
orig_total_out = pStream->total_out;
for (;;)
{
tdefl_status defl_status;
in_bytes = pStream->avail_in;
out_bytes = pStream->avail_out;

defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
pStream->next_in += (mz_uint)in_bytes;
pStream->avail_in -= (mz_uint)in_bytes;
pStream->total_in += (mz_uint)in_bytes;
pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);

pStream->next_out += (mz_uint)out_bytes;
pStream->avail_out -= (mz_uint)out_bytes;
pStream->total_out += (mz_uint)out_bytes;

if (defl_status < 0)
{
mz_status = MZ_STREAM_ERROR;
break;
}
else if (defl_status == TDEFL_STATUS_DONE)
{
mz_status = MZ_STREAM_END;
break;
}
else if (!pStream->avail_out)
break;
else if ((!pStream->avail_in) && (flush != MZ_FINISH))
{
if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
break;
return MZ_BUF_ERROR; /* Can't make forward progress without some input.
*/
}
}
return mz_status;
}

int mz_deflateEnd(mz_streamp pStream)
{
if (!pStream)
return MZ_STREAM_ERROR;
if (pStream->state)
{
pStream->zfree(pStream->opaque, pStream->state);
pStream->state = NULL;
}
return MZ_OK;
}
2 changes: 1 addition & 1 deletion src/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// glue sequential tzx/taps in zips (side A) -> side 1 etc)
// sequential tzx/taps/dsks do not reset model

#define SPECTRAL "v1.01"
#define SPECTRAL "v1.02 wip"

#define README \
"Spectral can be configured with a mouse.\n\n" \
Expand Down
2 changes: 2 additions & 0 deletions src/emu.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ int play(int sample, unsigned count); // this is from sys headers actually
#include "emu_ayumi.h"
#include "emu_fdc.h"
#include "emu_wd1793.h"
#define block block2
#include "emu_rzx.h"

#if! REDCODE

Expand Down
Loading

0 comments on commit 8daca50

Please sign in to comment.