1
0
mirror of https://github.com/fruit-bat/pico-zxspectrum.git synced 2025-04-19 00:04:01 +03:00

TZX block 11 - Turbo

This commit is contained in:
Phil 2022-10-30 15:20:25 +00:00
parent a5f9d99d0e
commit 74d7f258c6
12 changed files with 203 additions and 14 deletions

View File

@ -30,6 +30,7 @@ set(zxspectrum_common_src
${CMAKE_CURRENT_LIST_DIR}/PulseProcPulseStream.cpp
${CMAKE_CURRENT_LIST_DIR}/PulseProcTzxPulseSequence.cpp
${CMAKE_CURRENT_LIST_DIR}/PulseProcTzxPureData.cpp
${CMAKE_CURRENT_LIST_DIR}/PulseProcBitStream.cpp
${CMAKE_CURRENT_LIST_DIR}/ZxSpectrumFile.cpp

View File

@ -0,0 +1,35 @@
#include "PulseProcBitStream.h"
PulseProcBitStream::PulseProcBitStream(PulseProcTone* ppTone) :
_ppTone(ppTone),
_l(0)
{}
void PulseProcBitStream::init(
PulseProc *nxt,
uint32_t l,
uint32_t tspb,
uint32_t blb) {
next(nxt);
_l = l;
_tspb = tspb;
_blb = blb > 8 ? 8 : blb;
_b = 0x10000;
}
int32_t __not_in_flash_func(PulseProcBitStream::advance)(
InputStream *is,
bool *pstate,
PulseProc **top
) {
if (_l == 0) return PP_COMPLETE;
if (_b & 0x10000) {
int32_t r = is->readByte();
if (r < 0) return PP_ERROR;
_b = r | (1 << (_l == 1 ? (16 - _blb) : 8));
}
*pstate = (_b >> 7) & 1;
*top = _ppTone;
_b <<= 1;
return _tspb;
}

32
src/PulseProcBitStream.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <pico/stdlib.h>
#include "PulseProc.h"
#include "PulseProcTone.h"
class PulseProcBitStream : public PulseProc {
private:
PulseProcTone* _ppTone;
uint32_t _l;
uint32_t _tspb;
uint32_t _blb;
uint32_t _b;
public:
PulseProcBitStream(PulseProcTone* ppTone);
void init(
PulseProc *next,
uint32_t l,
uint32_t tspb,
uint32_t blb
);
virtual int32_t __not_in_flash_func(advance)(
InputStream *is,
bool *pstate,
PulseProc **top
);
};

View File

@ -2,12 +2,12 @@
PulseProcStdByte::PulseProcStdByte(PulseProcTone* t1) :
_t1(t1),
_b(0x10000)
_b(0x10000UL)
{}
void PulseProcStdByte::init(PulseProc *nxt, uint32_t b) {
next(nxt);
_b = b | 0x100;
_b = b | 0x100UL;
_ts[0] = 855;
_ts[1] = 1710;
}
@ -20,7 +20,7 @@ void __not_in_flash_func(PulseProcStdByte::init)(
uint32_t ts1
) {
next(nxt);
_b = b | (1 << (16 - (n > 8 ? 8 : n)));
_b = b | (1UL << (16 - (n > 8 ? 8 : n)));
_ts[0] = ts0;
_ts[1] = ts1;
}
@ -30,7 +30,7 @@ int32_t __not_in_flash_func(PulseProcStdByte::advance)(
bool *pstate,
PulseProc **top
) {
if (_b & 0x10000) return PP_COMPLETE;
if (_b & 0x10000UL) return PP_COMPLETE;
_t1->init(this, _ts[(_b >> 7) & 1], 2);
_b <<= 1;
*top = _t1;

View File

@ -38,11 +38,10 @@ int32_t __not_in_flash_func(PulseProcStdByteStream::advance)(
_ppb->init(
this,
r,
_l == 1 ? _blb : 8,
--_l == 0 ? _blb : 8,
_ts0,
_ts1
);
--_l;
*top = _ppb;
return PP_CONTINUE;
}

View File

@ -30,7 +30,8 @@ int32_t PulseProcTzx::advance(
_pptHeader.init(&_pptIndex);
_pptIndex.init(&_pptBlock, &_bi);
_pptBlock.init(next(), &_bi, _tsPerMs);
_pptBlock.init(&_lastPause, &_bi, _tsPerMs);
_lastPause.init(next(), 1000, _tsPerMs);
*top = &_pptHeader;
return PP_CONTINUE;

View File

@ -16,6 +16,7 @@ private:
PulseProcTzxIndex _pptIndex;
PulseProcTzxBlock _pptBlock;
uint32_t _tsPerMs;
PulseProcPauseMillis _lastPause;
public:

View File

@ -72,7 +72,7 @@ int32_t PulseProcTzxBlock::doStandardSpeedData(InputStream *is, PulseProc **top)
*/
int32_t PulseProcTzxBlock::doTurboSpeedData(InputStream *is, PulseProc **top) {
_ppTzxTurbo.init(this, _tsPerMs);
*top = _ppTap;
*top = &_ppTzxTurbo;
return PP_CONTINUE;
}
@ -82,7 +82,7 @@ int32_t PulseProcTzxBlock::doTurboSpeedData(InputStream *is, PulseProc **top) {
*/
int32_t PulseProcTzxBlock::doPureTone(InputStream *is, PulseProc **top) {
_ppTzxPureTone.init(this);
*top = _ppTap;
*top = &_ppTzxPureTone;
return PP_CONTINUE;
}
@ -92,7 +92,7 @@ int32_t PulseProcTzxBlock::doPureTone(InputStream *is, PulseProc **top) {
*/
int32_t PulseProcTzxBlock::doSequence(InputStream *is, PulseProc **top) {
_ppTzxPulseSequence.init(this);
*top = _ppTap;
*top = &_ppTzxPulseSequence;
return PP_CONTINUE;
}
@ -107,7 +107,7 @@ int32_t PulseProcTzxBlock::doSequence(InputStream *is, PulseProc **top) {
*/
int32_t PulseProcTzxBlock::doPureData(InputStream *is, PulseProc **top) {
_ppTzxPureData.init(this, _tsPerMs);
*top = _ppTap;
*top = &_ppTzxPureData;
return PP_CONTINUE;
}

View File

@ -0,0 +1,85 @@
#include "PulseProcTzxDirectRecording.h"
PulseProcTzxDirectRecording::PulseProcTzxDirectRecording(
PulseProcBitStream* data,
PulseProcTone* end,
PulseProcPauseMillis* pause
) :
_data(data),
_end(end),
_pause(pause)
{
}
void PulseProcTzxDirectRecording::init(
PulseProc *nxt,
uint32_t tsPerMs
) {
next(nxt);
_tsPerMs = tsPerMs;
}
/**
* ID 15 - Direct Recording
*
* length: [05,06,07]+08
*
* Offset Value Type Description
* 0x00 - WORD Number of T-states per sample (bit of data)
* 0x02 - WORD Pause after this block in milliseconds (ms.)
* 0x04 - BYTE Used bits (samples) in last byte of data (1-8)
* (e.g. if this is 2, only first two samples of the last byte will be played)
* 0x05 N BYTE[3] Length of samples' data
* 0x08 - BYTE[N] Samples data. Each bit represents a state on the EAR port (i.e. one sample).
* MSb is played first.
*/
int32_t __not_in_flash_func(PulseProcTzxDirectRecording::advance)(
InputStream *is,
bool *pstate,
PulseProc **top
) {
DBG_PULSE("PulseProcTzxDirectRecording: \n");
const int8_t l[] = { //TODO
2, // 0. WORD Number of T-states per sample (bit of data)
2, // 1. WORD Pause after this block in milliseconds (ms.)
1, // 2. BYTE Used bits (samples) in last byte of data (1-8)
3 // 3. BYTE[3] Length of samples' data
};
uint32_t h[5];
int32_t r = is->decodeLsbf(h, l, 5);
if (r < 0) {
DBG_PULSE("PulseProcTzxDirectRecording: Error (%ld) reading pure data header\n", r);
return PP_ERROR;
}
else {
DBG_PULSE("PulseProcTzxDirectRecording: Length of ZERO bit pulse %ld\n", h[0]);
DBG_PULSE("PulseProcTzxDirectRecording: Length of ONE bit pulse %ld\n", h[1]);
DBG_PULSE("PulseProcTzxDirectRecording: Used bits in the last byte %ld\n", h[2]);
DBG_PULSE("PulseProcTzxDirectRecording: Pause after this block %ld\n", h[3]);
DBG_PULSE("PulseProcTzxDirectRecording: Length of data that follow %ld\n", h[4]);
_data->init(
_end,
h[4], // 4. BYTE[3] Length of data that follow
h[0], // 0. WORD Length of ZERO bit pulse {855}
h[4], // 4. WORD Length of ONE bit pulse {1710}
h[2] // 2. BYTE Used bits in the last byte
);
_end->init(_pause, 0, 1);
_pause->init(
next(),
h[3], // 3. WORD Pause after this block (ms.) {1000}
_tsPerMs
);
*top = _data;
return PP_CONTINUE;
}
}

View File

@ -0,0 +1,35 @@
#pragma once
#include <pico/stdlib.h>
#include "PulseProc.h"
#include "PulseProcTone.h"
#include "PulseProcBitStream.h"
#include "PulseProcPauseMillis.h"
class PulseProcTzxDirectRecording : public PulseProc {
private:
PulseProcBitStream* _data;
PulseProcTone* _end;
PulseProcPauseMillis* _pause;
uint32_t _tsPerMs;
public:
PulseProcTzxDirectRecording(
PulseProcBitStream* data,
PulseProcTone* end,
PulseProcPauseMillis* pause
);
void init(
PulseProc *nxt,
uint32_t tsPerMs
);
virtual int32_t __not_in_flash_func(advance)(
InputStream *is,
bool *pstate,
PulseProc **top
);
};

BIN
test/tzx-test-block-11.tzx Normal file

Binary file not shown.