Files
raimon@prometeo fb5097733d -[NEW] reorganització de códi
-[NEW] mòdul display operatiu
-[NEW] mòdul tia pràcticament acabat (falta el reset)
-[NEW] glue code para poder compilar. Primera compilació
-[NEW] Afegides classes de UI
-[NEW] Afegides classes de debug desensamblador del z80, a convertir a 6502
2026-09-17 10:43:59 +02:00

188 lines
6.6 KiB
C++

#include "tia-audio.h"
namespace tia
{
namespace audio
{
static const uint16_t BIT_PATTERN_15 = 0x7556;
static const uint32_t BIT_PATTERN_31 = 0x74567254;
static const uint8_t LFSR511_TABLE[511] = {
1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,1,1,1,0,0,1,0,1,
0,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,
1,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,1,1,1,0,0,1,1,1,0,1,0,1,1,0,
1,0,0,0,1,1,0,1,1,0,0,0,1,1,0,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,
0,0,1,1,0,1,1,1,1,0,1,0,1,0,0,0,0,1,1,0,0,1,1,0,0,1,1,1,0,0,0,
1,0,0,0,0,1,0,0,1,0,1,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,1,
1,1,0,1,0,0,0,1,0,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,
1,0,0,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1,0,0,0,0,1,1,1,0,1,1,0,1,
1,1,0,0,1,0,1,1,0,1,1,0,0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,1,0,0,0,
1,0,1,1,1,1,0,0,1,0,1,0,0,0,1,0,1,1,0,1,0,1,1,1,0,1,1,0,0,0,0,
1,0,1,1,0,0,1,0,1,0,1,1,1,1,0,1,1,0,1,0,0,1,0,1,0,0,1,0,1,1,0,
0,0,0,0,1,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,0,0,0,1,0,1,0,
1,1,0,1,1,0,1,0,1,0,0,1,0,0,1,1,0,1,0,0,0,0,0,0,0,1,1,0,1,1,1,
0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,1,1,1,0,1,1,1,1,0,0,1,1,1,
1,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,1,0,
1,0,1,1,0,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1,0,0,1,1,0,1,1,1,0,1,0,
1,0,0,0,0,0,1,1
};
uint8_t get_lfsr511_bit(uint32_t step)
{
return LFSR511_TABLE[step % 511];
}
uint8_t get_poly_mode_bit(uint8_t audc, uint32_t step)
{
switch (audc & 0x0F) {
case 0:
case 11:
return 1; // Direct volume (PCM output)
case 1:
// 4-bit Poly (15 steps)
return (BIT_PATTERN_15 >> (step % 15)) & 1;
case 2:
// 5-bit Poly -> 4-bit Poly divisor (31 steps)
return (BIT_PATTERN_31 >> (step % 31)) & 1;
case 3: {
// 5-bit Poly XOR 4-bit Poly (465 steps)
uint8_t b5 = (BIT_PATTERN_31 >> (step % 31)) & 1;
uint8_t b4 = (BIT_PATTERN_15 >> (step % 15)) & 1;
return b5 ^ b4;
}
case 4:
case 5:
// Pure Tone: Divide frequency clock by 2
return (step & 1);
case 6:
case 10:
// Divide by 31 then divide by 2
return ((step / 31) & 1);
case 7:
case 9:
// 5-bit Poly output variant
return ((BIT_PATTERN_31 >> ((step / 2) % 31)) & 1);
case 8:
// White Noise (9-bit Poly / 511 steps)
return get_lfsr511_bit(step);
case 12:
case 13:
// Pure Tone: Divide frequency clock by 6
return ((step / 3) & 1);
case 14:
// Divide by 93 (31 * 3) then divide by 2
return ((step / 93) & 1);
case 15:
// 5-bit Poly clocked down by 6
return ((BIT_PATTERN_31 >> ((step / 6) % 31)) & 1);
default:
return 0;
}
}
struct channel
{
uint8_t control = 0;
uint8_t frequency = 0;
uint8_t volume = 0;
uint8_t freq_counter = 0;
uint32_t poly_counter = 0;
};
channel channels[2];
void tick()
{
for (int i=0; i<2; ++i) {
if (channels[i].freq_counter == 0) {
channels[i].freq_counter = channels[i].frequency + 1;
channels[i].poly_counter++;
} else {
channels[i].freq_counter--;
}
}
}
void write(uint16_t address, uint8_t value)
{
switch (address) {
case 0x15: // AUDC0
channels[0].control = value & 0x0f; break;
case 0x16: // AUDC1
channels[1].control = value & 0x0f; break;
case 0x17: // AUDF0
channels[0].frequency = value & 0x1f; break;
case 0x18: // AUDF1
channels[1].frequency = value & 0x1f; break;
case 0x19: // AUDV0
channels[0].volume = value & 0x0f; break;
case 0x1A: // AUDV1
channels[1].volume = value & 0x0f; break;
}
}
uint8_t get_sample0() { return get_sample(0); }
uint8_t get_sample1() { return get_sample(1); }
uint8_t get_sample(uint8_t channel)
{
if (channels[channel].volume == 0) return 0;
bool bit_out = false;
switch (channels[channel].control) {
case 0:
case 11:
// Set to 1: Direct volume output (PCM mode)
bit_out = true;
break;
case 1:
// 4-bit Poly (15-step repeating sequence)
bit_out = (BIT_PATTERN_15 >> (channels[channel].poly_counter % 15)) & 1;
break;
case 2:
// 5-bit Poly (31-step repeating sequence)
bit_out = (BIT_PATTERN_31 >> (channels[channel].poly_counter % 31)) & 1;
break;
case 4:
case 5:
// Pure tone (Divide by 2 square wave)
bit_out = (channels[channel].poly_counter & 1);
break;
case 8:
// White noise (9-bit Poly / 511-step sequence)
bit_out = get_lfsr511_bit(channels[channel].poly_counter % 511);
break;
case 12:
case 13:
// Pure tone (Divide by 6 square wave)
bit_out = ((channels[channel].poly_counter / 3) & 1);
break;
default:
// Handle remaining poly modes (3, 6, 7, 9, 10, 14, 15) via lookup table
bit_out = get_poly_mode_bit(channels[channel].control, channels[channel].poly_counter);
break;
}
return bit_out ? channels[channel].volume * 17 : 0;
}
}
}