Skip to content

Commit 9767e46

Browse files
Merge branch 'states'
2 parents ed530d1 + 3e6151c commit 9767e46

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1254
-87
lines changed

Diff for: ReleaseNotes.txt

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
v2.1.0 - October 27, 2014
2+
- Added support for saving and loading Intellivision game states.
3+
- Refactored code for multi-platform support.
4+
See https://github.com/jeremiah-sypult/BlissEmu and
5+
https://github.com/OpenEmu/OpenEmu
6+
17
v2.0.5 - May 25, 2005
28
- Added support for the Classic Game Controller (CGC).
39
See http://www.shiny-technologies.com/cgc.php for details on this device.

Diff for: ToDo.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
- offer the ability to display the overlays somehow, maybe as a toggle display for the
44
lower left and right sides of the screen
55
- input
6+
- move Classic Game Controller (CGC) support code out of core (Windows)
67
- bug where I can't add bindings to the ECS keyboard default bindings; have to clear the
78
binding first because it's getting confused somehow
89
- allow the user to custom-bind different controls to different games
910
- saving and loading
10-
- saving and loading game state
11+
- saving and loading atari 5200 game state
1112
- saving screenshots
1213
- record/playback (save the inputs and play them back)
1314
- record audio

Diff for: core/Emulator.cpp

+28-25
Original file line numberDiff line numberDiff line change
@@ -58,52 +58,56 @@ void Emulator::UsePeripheral(UINT32 i, BOOL b)
5858

5959
UINT32 Emulator::GetVideoWidth()
6060
{
61-
return videoWidth;
61+
return videoWidth;
6262
}
6363

6464
UINT32 Emulator::GetVideoHeight()
6565
{
66-
return videoHeight;
66+
return videoHeight;
6767
}
6868

6969
void Emulator::InitVideo(VideoBus* video, UINT32 width, UINT32 height)
7070
{
71-
if ( video != NULL ) {
72-
videoBus = video;
73-
}
71+
if ( video != NULL ) {
72+
videoBus = video;
73+
}
7474

7575
videoBus->init(width, height);
7676
}
7777

7878
void Emulator::ReleaseVideo()
7979
{
80-
videoBus->release();
81-
videoBus = NULL;
80+
if (videoBus) {
81+
videoBus->release();
82+
videoBus = NULL;
83+
}
8284
}
8385

8486
void Emulator::InitAudio(AudioMixer* audio, UINT32 sampleRate)
8587
{
86-
if (audio != NULL) {
87-
audioMixer = audio;
88-
}
88+
if (audio != NULL) {
89+
audioMixer = audio;
90+
}
8991

90-
// TODO: check for an existing audioMixer processor and release it
91-
for (UINT16 i = 0; i < GetProcessorCount(); i++) {
92-
Processor* p = GetProcessor(i);
93-
if (p == audio) {
94-
RemoveProcessor(audio);
95-
}
96-
}
92+
// TODO: check for an existing audioMixer processor and release it
93+
for (UINT16 i = 0; i < GetProcessorCount(); i++) {
94+
Processor* p = GetProcessor(i);
95+
if (p == audio) {
96+
RemoveProcessor(audio);
97+
}
98+
}
9799

98-
AddProcessor(audioMixer);
99-
audioMixer->init(sampleRate);
100+
AddProcessor(audioMixer);
101+
audioMixer->init(sampleRate);
100102
}
101103

102104
void Emulator::ReleaseAudio()
103105
{
104-
audioMixer->release();
105-
RemoveProcessor(audioMixer);
106-
audioMixer = NULL;
106+
if (audioMixer) {
107+
audioMixer->release();
108+
RemoveProcessor(audioMixer);
109+
audioMixer = NULL;
110+
}
107111
}
108112

109113
void Emulator::Reset()
@@ -141,7 +145,7 @@ void Emulator::SetRip(Rip* rip)
141145

142146
void Emulator::InsertPeripheral(Peripheral* p)
143147
{
144-
UINT16 i;
148+
UINT16 i;
145149

146150
//processors
147151
UINT16 count = p->GetProcessorCount();
@@ -179,7 +183,7 @@ void Emulator::InsertPeripheral(Peripheral* p)
179183

180184
void Emulator::RemovePeripheral(Peripheral* p)
181185
{
182-
UINT16 i;
186+
UINT16 i;
183187

184188
//processors
185189
UINT16 count = p->GetProcessorCount();
@@ -240,4 +244,3 @@ Emulator* Emulator::emus[] = {
240244
&atari5200,
241245
&inty,
242246
};
243-

Diff for: core/Emulator.h

+31-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,30 @@
1616
#include "core/memory/MemoryBus.h"
1717
#include "core/memory/Memory.h"
1818

19+
typedef struct _StateHeader
20+
{
21+
UINT32 emu;
22+
UINT32 state;
23+
UINT32 emuID;
24+
UINT32 version;
25+
UINT32 sys;
26+
UINT32 sysID;
27+
UINT32 cart;
28+
UINT32 cartID;
29+
} StateHeader;
30+
31+
typedef struct _StateChunk
32+
{
33+
UINT32 id;
34+
UINT32 size;
35+
} StateChunk;
36+
37+
#if defined(DEBUG)
38+
#define EMU_STATE_VERSION ('dev\0')
39+
#else
40+
#define EMU_STATE_VERSION (0x02010000)
41+
#endif
42+
1943
class Intellivision;
2044
class Atari5200;
2145

@@ -49,6 +73,9 @@ class Emulator : public Peripheral
4973
void FlushAudio();
5074
void Render();
5175

76+
virtual BOOL SaveState(const CHAR* filename) = 0;
77+
virtual BOOL LoadState(const CHAR* filename) = 0;
78+
5279
static UINT32 GetEmulatorCount();
5380
static Emulator* GetEmulator(UINT32 i);
5481
static Emulator* GetEmulatorByID(UINT32 targetSystemID);
@@ -58,8 +85,10 @@ class Emulator : public Peripheral
5885

5986
MemoryBus memoryBus;
6087

61-
UINT32 videoWidth;
62-
UINT32 videoHeight;
88+
Rip* currentRip;
89+
90+
UINT32 videoWidth;
91+
UINT32 videoHeight;
6392

6493
private:
6594
ProcessorBus processorBus;
@@ -70,8 +99,6 @@ class Emulator : public Peripheral
7099
void InsertPeripheral(Peripheral* p);
71100
void RemovePeripheral(Peripheral* p);
72101

73-
Rip* currentRip;
74-
75102
Peripheral* peripherals[MAX_PERIPHERALS];
76103
BOOL usePeripheralIndicators[MAX_PERIPHERALS];
77104
INT32 peripheralCount;
@@ -84,4 +111,3 @@ class Emulator : public Peripheral
84111
};
85112

86113
#endif
87-

Diff for: core/audio/AY38914.cpp

+67
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,70 @@ INT32 AY38914::tick(INT32 minimum)
221221
return totalTicks;
222222
}
223223

224+
AY38914State AY38914::getState()
225+
{
226+
AY38914State state = {0};
227+
228+
this->registers.getMemory(state.registers, 0, this->registers.getMemoryByteSize());
229+
230+
state.clockDivisor = this->clockDivisor;
231+
232+
state.channel0 = this->channel0.getState();
233+
state.channel1 = this->channel1.getState();
234+
state.channel2 = this->channel2.getState();
235+
236+
state.cachedTotalOutputIsDirty = this->cachedTotalOutputIsDirty;
237+
state.cachedTotalOutput = this->cachedTotalOutput;
238+
239+
state.envelopeIdle = this->envelopeIdle;
240+
state.envelopePeriod = this->envelopePeriod;
241+
state.envelopePeriodValue = this->envelopePeriodValue;
242+
state.envelopeCounter = this->envelopeCounter;
243+
state.envelopeVolume = this->envelopeVolume;
244+
state.envelopeHold = this->envelopeHold;
245+
state.envelopeAltr = this->envelopeAltr;
246+
state.envelopeAtak = this->envelopeAtak;
247+
state.envelopeCont = this->envelopeCont;
248+
249+
state.noiseIdle = this->noiseIdle;
250+
state.noisePeriod = this->noisePeriod;
251+
state.noisePeriodValue = this->noisePeriodValue;
252+
state.noiseCounter = this->noiseCounter;
253+
254+
state.random = this->random;
255+
state.noise = this->noise;
256+
257+
return state;
258+
}
259+
260+
void AY38914::setState(AY38914State state)
261+
{
262+
this->registers.setMemory(state.registers, 0, this->registers.getMemoryByteSize());
263+
264+
this->clockDivisor = state.clockDivisor;
265+
266+
this->channel0.setState(state.channel0);
267+
this->channel1.setState(state.channel1);
268+
this->channel2.setState(state.channel2);
269+
270+
this->cachedTotalOutputIsDirty = state.cachedTotalOutputIsDirty;
271+
this->cachedTotalOutput = state.cachedTotalOutput;
272+
273+
this->envelopeIdle = state.envelopeIdle;
274+
this->envelopePeriod = state.envelopePeriod;
275+
this->envelopePeriodValue = state.envelopePeriodValue;
276+
this->envelopeCounter = state.envelopeCounter;
277+
this->envelopeVolume = state.envelopeVolume;
278+
this->envelopeHold = state.envelopeHold;
279+
this->envelopeAltr = state.envelopeAltr;
280+
this->envelopeAtak = state.envelopeAtak;
281+
this->envelopeCont = state.envelopeCont;
282+
283+
this->noiseIdle = state.noiseIdle;
284+
this->noisePeriod = state.noisePeriod;
285+
this->noisePeriodValue = state.noisePeriodValue;
286+
this->noiseCounter = state.noiseCounter;
287+
288+
this->random = state.random;
289+
this->noise = state.noise;
290+
}

Diff for: core/audio/AY38914.h

+29-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@
1212

1313
class Intellivision;
1414

15+
TYPEDEF_STRUCT_PACK( _AY38914State
16+
{
17+
UINT16 registers[0x0E];
18+
AY38914_ChannelState channel0;
19+
AY38914_ChannelState channel1;
20+
AY38914_ChannelState channel2;
21+
INT32 clockDivisor;
22+
INT32 cachedTotalOutput;
23+
INT32 envelopePeriod;
24+
INT32 envelopePeriodValue;
25+
INT32 envelopeCounter;
26+
INT32 envelopeVolume;
27+
INT32 noisePeriod;
28+
INT32 noisePeriodValue;
29+
INT32 noiseCounter;
30+
INT32 random;
31+
INT8 cachedTotalOutputIsDirty;
32+
INT8 envelopeIdle;
33+
INT8 envelopeHold;
34+
INT8 envelopeAltr;
35+
INT8 envelopeAtak;
36+
INT8 envelopeCont;
37+
INT8 noiseIdle;
38+
INT8 noise;
39+
} AY38914State; )
40+
1541
/**
1642
* The AY-3-8914 chip in the Intellivision, also known as the Programmable
1743
* Sound Generator (PSG).
@@ -35,6 +61,9 @@ class AY38914 : public Processor, public AudioProducer
3561
void setClockDivisor(INT32 clockDivisor);
3662
INT32 getClockDivisor();
3763

64+
AY38914State getState();
65+
void setState(AY38914State state);
66+
3867
//registers
3968
AY38914_Registers registers;
4069

@@ -77,8 +106,6 @@ class AY38914 : public Processor, public AudioProducer
77106

78107
//output amplitudes for a single channel
79108
static const INT32 amplitudes16Bit[16];
80-
81109
};
82110

83111
#endif
84-

Diff for: core/audio/AY38914_Channel.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,33 @@ void AY38914_Channel::reset() {
1313
isDirty = TRUE;
1414
cachedSample = 0;
1515
}
16+
17+
AY38914_ChannelState AY38914_Channel::getState()
18+
{
19+
AY38914_ChannelState state = {0};
20+
21+
state.period = this->period;
22+
state.periodValue = this->periodValue;
23+
state.volume = this->volume;
24+
state.toneCounter = this->toneCounter;
25+
state.tone = this->tone;
26+
state.envelope = this->envelope;
27+
state.toneDisabled = this->toneDisabled;
28+
state.noiseDisabled = this->noiseDisabled;
29+
30+
return state;
31+
}
32+
33+
void AY38914_Channel::setState(AY38914_ChannelState state)
34+
{
35+
this->period = state.period;
36+
this->periodValue = state.periodValue;
37+
this->volume = state.volume;
38+
this->toneCounter = state.toneCounter;
39+
this->tone = state.tone;
40+
this->envelope = state.envelope;
41+
this->toneDisabled = state.toneDisabled;
42+
this->noiseDisabled = state.noiseDisabled;
43+
44+
this->isDirty = TRUE;
45+
}

Diff for: core/audio/AY38914_Channel.h

+15-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,27 @@
77
class AY38914;
88
class AY38914_Registers;
99

10+
TYPEDEF_STRUCT_PACK( _AY38914_ChannelState
11+
{
12+
INT32 period;
13+
INT32 periodValue;
14+
INT32 volume;
15+
INT32 toneCounter;
16+
INT8 tone;
17+
INT8 envelope;
18+
INT8 toneDisabled;
19+
INT8 noiseDisabled;
20+
} AY38914_ChannelState; )
21+
1022
class AY38914_Channel
1123
{
1224

1325
friend class AY38914;
1426
friend class AY38914_Registers;
1527

28+
AY38914_ChannelState getState();
29+
void setState(AY38914_ChannelState state);
30+
1631
private:
1732
void reset();
1833

@@ -26,8 +41,6 @@ class AY38914_Channel
2641
BOOL noiseDisabled;
2742
BOOL isDirty;
2843
INT32 cachedSample;
29-
3044
};
3145

3246
#endif
33-

0 commit comments

Comments
 (0)