more audio cleanup

This commit is contained in:
Jorj Bauer 2017-08-27 08:07:24 -04:00
parent 89a6450a91
commit 5d85c2204a
5 changed files with 13 additions and 251 deletions

View File

@ -1,181 +0,0 @@
#include "sy6522.h"
#include <stdio.h>
#include "globals.h"
SY6522::SY6522()
{
ORB = ORA = 0;
DDRB = DDRA = 0x00;
T1_CTR = T2_CTR = 0;
T1_CTR_LATCH = T2_CTR_LATCH = 0;
ACR = 0x20; // free-running; FIXME: constant?
PCR = 0xB0; // FIXME: ?
IFR = 0x00; // FIXME: ?
IER = 0x90; // FIXME: ?
}
uint8_t SY6522::read(uint8_t address)
{
switch (address) {
case SY_ORB:
return ORB;
case SY_ORA:
return ORA;
case SY_DDRB:
return DDRB;
case SY_DDRA:
return DDRA;
case SY_TMR1L:
IFR &= ~SY_IR_TIMER1;
return (T1_CTR & 0xFF);
case SY_TMR1H:
return (T1_CTR >> 8);
case SY_TMR1LL:
return (T1_CTR_LATCH & 0xFF);
case SY_TMR1HL:
return (T1_CTR_LATCH >> 8);
case SY_TMR2L:
IFR &= ~SY_IR_TIMER2;
return (T2_CTR & 0xFF);
case SY_TMR2H:
return (T2_CTR >> 8);
case SY_SS:
// FIXME: floating
return 0xFF;
case SY_ACR:
return ACR;
case SY_PCR:
return PCR;
case SY_IFR:
return IFR;
case SY_IER:
return 0x80 | IER;
case SY_ORANOHS:
return ORA;
}
return 0xFF;
}
void SY6522::write(uint8_t address, uint8_t val)
{
switch (address) {
case SY_ORB:
val &= DDRB;
ORB = val;
ay8910[0].write(val, ORA & DDRA);
return;
case SY_ORA:
ORA = val & DDRA;
return;
case SY_DDRB:
DDRB = val;
return;
case SY_DDRA:
DDRA = val;
return;
case SY_TMR1L:
case SY_TMR1LL:
T1_CTR_LATCH = (T1_CTR_LATCH & 0xFF00) | val;
return;
case SY_TMR1H:
IFR &= SY_IR_TIMER1;
// Update IFR?
IFR &= 0x7F;
if (IFR & IER) {
// an interrupt is happening; keep the IE flag on
IFR |= 0x80;
}
// FIXME: clear interrupt flag
T1_CTR_LATCH = (T1_CTR_LATCH & 0x00FF) | (val << 8);
T1_CTR = T1_CTR_LATCH;
// FIXME: start timer?
return;
case SY_TMR1HL:
T1_CTR_LATCH = (T1_CTR_LATCH & 0x00FF) | (val << 8);
// FIXME: clear interrupt flag
return;
case SY_TMR2L:
T2_CTR_LATCH = (T2_CTR_LATCH & 0xFF00) | val;
return;
case SY_TMR2H:
// FIXME: clear timer2 interrupt flag
T2_CTR_LATCH = (T2_CTR_LATCH & 0x00FF) | (val << 8);
T2_CTR = T2_CTR_LATCH;
return;
case SY_SS:
// FIXME: what is this for?
return;
case SY_ACR:
ACR = val;
break;
case SY_PCR:
PCR = val;
break;
case SY_IFR:
// Clear whatever low bits are set in IFR.
val |= 0x80;
val ^= 0x7F;
IFR &= val;
break;
case SY_IER:
if (val & 0x80) {
// Set bits based on val
val &= 0x7F;
IER |= val;
// FIXME: start timer if necessary?
} else {
// Clear whatever low bits are set in IER.
val |= 0x80;
val ^= 0x7F;
IER &= val;
// FIXME: stop timer if it's running?
}
return;
case SY_ORANOHS:
// FIXME: what is this for?
return;
}
}
void SY6522::update(uint32_t cycles)
{
/* Update 6522 timers */
// ...
/*
SY_IR_CA2 = 1,
SY_IR_CA1 = 2,
SY_IR_SHIFTREG = 4,
SY_IR_CB2 = 8,
SY_IR_CB1 = 16,
SY_IR_TIMER2 = 32,
SY_IR_TIMER1 = 64,
SY_IER_SETCLEAR = 128,
SY_IFR_IRQ = 128
*/
/* Check for 6522 interrupts */
if (IFR & 0x80) {
g_cpu->stageIRQ();
}
/* Update the attached 8910 chip(s) */
ay8910[0].update(cycles);
}

View File

@ -1,67 +0,0 @@
#ifndef __SY6522_H
#define __SY6522_H
#include <stdint.h>
#include "ay8910.h"
// 6522 interface registers
enum {
SY_ORB = 0x00, // ORB
SY_ORA = 0x01, // ORA
SY_DDRB = 0x02, // DDRB
SY_DDRA = 0x03, // DDRA
SY_TMR1L = 0x04, // TIMER1L_COUNTER
SY_TMR1H = 0x05, // TIMER1H_COUNTER
SY_TMR1LL = 0x06, // TIMER1L_LATCH
SY_TMR1HL = 0x07, // TIMER1H_LATCH
SY_TMR2L = 0x08, // TIMER2L
SY_TMR2H = 0x09, // TIMER2H
SY_SS = 0x0a, // SERIAL_SHIFT
SY_ACR = 0x0b, // ACR
SY_PCR = 0x0c, // PCR
SY_IFR = 0x0d, // IFR
SY_IER = 0x0e, // IER
SY_ORANOHS = 0x0f // ORA_NO_HS
};
// IFR and IER share the names of all but the high bit
enum {
SY_IR_CA2 = 1,
SY_IR_CA1 = 2,
SY_IR_SHIFTREG = 4,
SY_IR_CB2 = 8,
SY_IR_CB1 = 16,
SY_IR_TIMER2 = 32,
SY_IR_TIMER1 = 64,
SY_IER_SETCLEAR = 128,
SY_IFR_IRQ = 128
};
class SY6522 {
public:
SY6522();
uint8_t read(uint8_t address);
void write(uint8_t address, uint8_t val);
void update(uint32_t cycles);
private:
uint8_t ORB; // port B
uint8_t ORA; // port A
uint8_t DDRB; // data direction register
uint8_t DDRA; //
uint16_t T1_CTR; // counters
uint16_t T1_CTR_LATCH;
uint16_t T2_CTR;
uint16_t T2_CTR_LATCH;
uint8_t ACR; // Aux Control Register
uint8_t PCR; // Peripheral Control Register
uint8_t IFR; // Interrupt Flag Register
uint8_t IER; // Interrupt Enable Register
AY8910 ay8910[1]; // FIXME: an array in case we support more than one ... ?
};
#endif

View File

@ -1 +0,0 @@
../apple/sy6522.cpp

View File

@ -1 +0,0 @@
../apple/sy6522.h

View File

@ -226,7 +226,6 @@ void runCPU()
((AppleVM *)g_vm)->cpuMaintenance(g_cpu->cycles);
g_speaker->maintainSpeaker(g_cpu->cycles);
// The CPU of the Apple //e ran at 1.023 MHz. Adjust when we think
// the next instruction should run based on how long the execution
// was ((1000/1023) * numberOfCycles) - which is about 97.8%.
@ -252,6 +251,19 @@ void loop()
// Only redraw if the CPU is caught up; and then we'll suspend the
// CPU to draw a full frame.
// Note that this breaks audio, b/c it's real-time and requires the
// CPU running to change the audio line's value. So we need to EITHER
//
// - delay the audio line by at least the time it takes for one
// display update, OR
// - lock display updates so the CPU can update the memory, but we
// keep drawing what was going to be displayed
//
// The Timer1.stop()/start() is bad. Using it, the display doesn't
// tear; but the audio is also broken. Taking it out, audio is good
// but the display tears.
Timer1.stop();
g_vm->vmdisplay->needsRedraw();
AiieRect what = g_vm->vmdisplay->getDirtyRect();