mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-11-25 19:31:36 +00:00
more audio cleanup
This commit is contained in:
parent
89a6450a91
commit
5d85c2204a
181
apple/sy6522.cpp
181
apple/sy6522.cpp
@ -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);
|
||||
}
|
||||
|
@ -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
|
@ -1 +0,0 @@
|
||||
../apple/sy6522.cpp
|
@ -1 +0,0 @@
|
||||
../apple/sy6522.h
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user