1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef TIA_DELAY_QUEUE_MEMBER
19#define TIA_DELAY_QUEUE_MEMBER
20
21#include "Serializable.hxx"
22#include "bspf.hxx"
23
24template<unsigned capacity>
25class DelayQueueMember : public Serializable {
26
27 public:
28 struct Entry {
29 uInt8 address;
30 uInt8 value;
31
32 Entry() : address(0), value(0) { }
33 };
34
35 public:
36 DelayQueueMember();
37
38 public:
39 void push(uInt8 address, uInt8 value);
40
41 void remove(uInt8 address);
42
43 void clear();
44
45 /**
46 Serializable methods (see that class for more information).
47 */
48 bool save(Serializer& out) const override;
49 bool load(Serializer& in) override;
50
51 public:
52 Entry myEntries[capacity];
53 uInt8 mySize;
54
55 private:
56 DelayQueueMember(const DelayQueueMember<capacity>&) = delete;
57 DelayQueueMember(DelayQueueMember<capacity>&&) = delete;
58 DelayQueueMember<capacity>& operator=(const DelayQueueMember<capacity>&) = delete;
59 DelayQueueMember<capacity>& operator=(DelayQueueMember<capacity>&&) = delete;
60
61};
62
63// ############################################################################
64// Implementation
65// ############################################################################
66
67// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68template<unsigned capacity>
69DelayQueueMember<capacity>::DelayQueueMember()
70 : mySize(0)
71{
72}
73
74// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
75template<unsigned capacity>
76void DelayQueueMember<capacity>::push(uInt8 address, uInt8 value)
77{
78 if (mySize == capacity) throw runtime_error("delay queue overflow");
79
80 myEntries[mySize].address = address;
81 myEntries[mySize++].value = value;
82}
83
84// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
85template<unsigned capacity>
86void DelayQueueMember<capacity>::remove(uInt8 address)
87{
88 uInt8 index;
89
90 for (index = 0; index < mySize; ++index) {
91 if (myEntries[index].address == address) break;
92 }
93
94 if (index < mySize) {
95 for (uInt8 i = index + 1; i < mySize; ++i) {
96 myEntries[i-1] = myEntries[i];
97 }
98
99 --mySize;
100 }
101}
102
103// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
104template<unsigned capacity>
105void DelayQueueMember<capacity>::clear()
106{
107 mySize = 0;
108}
109
110// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111template<unsigned capacity>
112bool DelayQueueMember<capacity>::save(Serializer& out) const
113{
114 try
115 {
116 out.putByte(mySize);
117 for(uInt8 i = 0; i < mySize; ++i)
118 {
119 const Entry& e = myEntries[i];
120 out.putByte(e.address);
121 out.putByte(e.value);
122 }
123 }
124 catch(...)
125 {
126 cerr << "ERROR: TIA_DelayQueueMember::save" << endl;
127 return false;
128 }
129
130 return true;
131}
132
133// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134template<unsigned capacity>
135bool DelayQueueMember<capacity>::load(Serializer& in)
136{
137 try
138 {
139 mySize = in.getByte();
140 if (mySize > capacity) throw new runtime_error("invalid delay queue size");
141 for(uInt32 i = 0; i < mySize; ++i)
142 {
143 Entry& e = myEntries[i];
144 e.address = in.getByte();
145 e.value = in.getByte();
146 }
147 }
148 catch(...)
149 {
150 cerr << "ERROR: TIA_DelayQueueMember::load" << endl;
151 return false;
152 }
153
154 return true;
155}
156
157#endif // TIA_DELAY_QUEUE_MEMBER
158