| 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 | #include "DataGridWidget.hxx" | 
|---|
| 19 | #include "GuiObject.hxx" | 
|---|
| 20 | #include "Font.hxx" | 
|---|
| 21 | #include "OSystem.hxx" | 
|---|
| 22 | #include "Debugger.hxx" | 
|---|
| 23 | #include "TIADebug.hxx" | 
|---|
| 24 | #include "Widget.hxx" | 
|---|
| 25 | #include "Base.hxx" | 
|---|
| 26 | using Common::Base; | 
|---|
| 27 |  | 
|---|
| 28 | #include "AudioWidget.hxx" | 
|---|
| 29 |  | 
|---|
| 30 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 31 | AudioWidget::AudioWidget(GuiObject* boss, const GUI::Font& lfont, | 
|---|
| 32 | const GUI::Font& nfont, | 
|---|
| 33 | int x, int y, int w, int h) | 
|---|
| 34 | : Widget(boss, lfont, x, y, w, h), | 
|---|
| 35 | CommandSender(boss) | 
|---|
| 36 | { | 
|---|
| 37 | const int fontWidth  = lfont.getMaxCharWidth(), | 
|---|
| 38 | fontHeight = lfont.getFontHeight(), | 
|---|
| 39 | lineHeight = lfont.getLineHeight(); | 
|---|
| 40 | int xpos = 10, ypos = 25, lwidth = lfont.getStringWidth( "AUDW "); | 
|---|
| 41 |  | 
|---|
| 42 | // AudF registers | 
|---|
| 43 | new StaticTextWidget(boss, lfont, xpos, ypos+2, | 
|---|
| 44 | lwidth, fontHeight, | 
|---|
| 45 | "AUDF", TextAlign::Left); | 
|---|
| 46 | xpos += lwidth; | 
|---|
| 47 | myAudF = new DataGridWidget(boss, nfont, xpos, ypos, | 
|---|
| 48 | 2, 1, 2, 5, Common::Base::F_16); | 
|---|
| 49 | myAudF->setTarget(this); | 
|---|
| 50 | myAudF->setID(kAUDFID); | 
|---|
| 51 | addFocusWidget(myAudF); | 
|---|
| 52 |  | 
|---|
| 53 | for(int col = 0; col < 2; ++col) | 
|---|
| 54 | { | 
|---|
| 55 | new StaticTextWidget(boss, lfont, xpos + col * myAudF->colWidth() + int(myAudF->colWidth() / 2.75), | 
|---|
| 56 | ypos - lineHeight, fontWidth, fontHeight, | 
|---|
| 57 | Common::Base::toString(col, Common::Base::F_16_1), | 
|---|
| 58 | TextAlign::Left); | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | // AudC registers | 
|---|
| 62 | xpos = 10;  ypos += lineHeight + 5; | 
|---|
| 63 | new StaticTextWidget(boss, lfont, xpos, ypos+2, lwidth, fontHeight, | 
|---|
| 64 | "AUDC", TextAlign::Left); | 
|---|
| 65 | xpos += lwidth; | 
|---|
| 66 | myAudC = new DataGridWidget(boss, nfont, xpos + int(myAudF->colWidth() / 2.75), ypos, | 
|---|
| 67 | 2, 1, 1, 4, Common::Base::F_16_1); | 
|---|
| 68 | myAudC->setTarget(this); | 
|---|
| 69 | myAudC->setID(kAUDCID); | 
|---|
| 70 | addFocusWidget(myAudC); | 
|---|
| 71 |  | 
|---|
| 72 | // AudV registers | 
|---|
| 73 | xpos = 10;  ypos += lineHeight + 5; | 
|---|
| 74 | new StaticTextWidget(boss, lfont, xpos, ypos+2, lwidth, fontHeight, | 
|---|
| 75 | "AUDV", TextAlign::Left); | 
|---|
| 76 | xpos += lwidth; | 
|---|
| 77 | myAudV = new DataGridWidget(boss, nfont, xpos + int(myAudF->colWidth() / 2.75), ypos, | 
|---|
| 78 | 2, 1, 1, 4, Common::Base::F_16_1); | 
|---|
| 79 | myAudV->setTarget(this); | 
|---|
| 80 | myAudV->setID(kAUDVID); | 
|---|
| 81 | addFocusWidget(myAudV); | 
|---|
| 82 |  | 
|---|
| 83 | myAudEffV = new StaticTextWidget(boss, lfont, myAudV->getRight() + fontWidth, myAudV->getTop() + 2, | 
|---|
| 84 | "100% (eff. volume)"); | 
|---|
| 85 | } | 
|---|
| 86 |  | 
|---|
| 87 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 88 | void AudioWidget::loadConfig() | 
|---|
| 89 | { | 
|---|
| 90 | IntArray alist; | 
|---|
| 91 | IntArray vlist; | 
|---|
| 92 | BoolArray blist, changed, grNew, grOld; | 
|---|
| 93 |  | 
|---|
| 94 | Debugger& dbg = instance().debugger(); | 
|---|
| 95 | TIADebug& tia = dbg.tiaDebug(); | 
|---|
| 96 | const TiaState& state    = static_cast<const TiaState&>(tia.getState()); | 
|---|
| 97 | const TiaState& oldstate = static_cast<const TiaState&>(tia.getOldState()); | 
|---|
| 98 |  | 
|---|
| 99 | // AUDF0/1 | 
|---|
| 100 | alist.clear();  vlist.clear();  changed.clear(); | 
|---|
| 101 | for(uInt32 i = 0; i < 2; ++i) | 
|---|
| 102 | { | 
|---|
| 103 | alist.push_back(i); | 
|---|
| 104 | vlist.push_back(state.aud[i]); | 
|---|
| 105 | changed.push_back(state.aud[i] != oldstate.aud[i]); | 
|---|
| 106 | } | 
|---|
| 107 | myAudF->setList(alist, vlist, changed); | 
|---|
| 108 |  | 
|---|
| 109 | // AUDC0/1 | 
|---|
| 110 | alist.clear();  vlist.clear();  changed.clear(); | 
|---|
| 111 | for(uInt32 i = 2; i < 4; ++i) | 
|---|
| 112 | { | 
|---|
| 113 | alist.push_back(i-2); | 
|---|
| 114 | vlist.push_back(state.aud[i]); | 
|---|
| 115 | changed.push_back(state.aud[i] != oldstate.aud[i]); | 
|---|
| 116 | } | 
|---|
| 117 | myAudC->setList(alist, vlist, changed); | 
|---|
| 118 |  | 
|---|
| 119 | // AUDV0/1 | 
|---|
| 120 | alist.clear();  vlist.clear();  changed.clear(); | 
|---|
| 121 | for(uInt32 i = 4; i < 6; ++i) | 
|---|
| 122 | { | 
|---|
| 123 | alist.push_back(i-4); | 
|---|
| 124 | vlist.push_back(state.aud[i]); | 
|---|
| 125 | changed.push_back(state.aud[i] != oldstate.aud[i]); | 
|---|
| 126 | } | 
|---|
| 127 | myAudV->setList(alist, vlist, changed); | 
|---|
| 128 |  | 
|---|
| 129 | handleVolume(); | 
|---|
| 130 | } | 
|---|
| 131 |  | 
|---|
| 132 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 133 | void AudioWidget::handleVolume() | 
|---|
| 134 | { | 
|---|
| 135 | stringstream s; | 
|---|
| 136 |  | 
|---|
| 137 | s << getEffectiveVolume() << "% (eff. volume)"; | 
|---|
| 138 | myAudEffV->setLabel(s.str()); | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 142 | void AudioWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) | 
|---|
| 143 | { | 
|---|
| 144 | switch(cmd) | 
|---|
| 145 | { | 
|---|
| 146 | case DataGridWidget::kItemDataChangedCmd: | 
|---|
| 147 | switch(id) | 
|---|
| 148 | { | 
|---|
| 149 | case kAUDFID: | 
|---|
| 150 | changeFrequencyRegs(); | 
|---|
| 151 | break; | 
|---|
| 152 |  | 
|---|
| 153 | case kAUDCID: | 
|---|
| 154 | changeControlRegs(); | 
|---|
| 155 | break; | 
|---|
| 156 |  | 
|---|
| 157 | case kAUDVID: | 
|---|
| 158 | changeVolumeRegs(); | 
|---|
| 159 | break; | 
|---|
| 160 |  | 
|---|
| 161 | default: | 
|---|
| 162 | cerr << "AudioWidget DG changed\n"; | 
|---|
| 163 | break; | 
|---|
| 164 | } | 
|---|
| 165 | break; | 
|---|
| 166 | } | 
|---|
| 167 | } | 
|---|
| 168 |  | 
|---|
| 169 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 170 | void AudioWidget::changeFrequencyRegs() | 
|---|
| 171 | { | 
|---|
| 172 | int addr = myAudF->getSelectedAddr(); | 
|---|
| 173 | int value = myAudF->getSelectedValue(); | 
|---|
| 174 |  | 
|---|
| 175 | switch(addr) | 
|---|
| 176 | { | 
|---|
| 177 | case kAud0Addr: | 
|---|
| 178 | instance().debugger().tiaDebug().audF0(value); | 
|---|
| 179 | break; | 
|---|
| 180 |  | 
|---|
| 181 | case kAud1Addr: | 
|---|
| 182 | instance().debugger().tiaDebug().audF1(value); | 
|---|
| 183 | break; | 
|---|
| 184 | } | 
|---|
| 185 | } | 
|---|
| 186 |  | 
|---|
| 187 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 188 | void AudioWidget::changeControlRegs() | 
|---|
| 189 | { | 
|---|
| 190 | int addr = myAudC->getSelectedAddr(); | 
|---|
| 191 | int value = myAudC->getSelectedValue(); | 
|---|
| 192 |  | 
|---|
| 193 | switch(addr) | 
|---|
| 194 | { | 
|---|
| 195 | case kAud0Addr: | 
|---|
| 196 | instance().debugger().tiaDebug().audC0(value); | 
|---|
| 197 | break; | 
|---|
| 198 |  | 
|---|
| 199 | case kAud1Addr: | 
|---|
| 200 | instance().debugger().tiaDebug().audC1(value); | 
|---|
| 201 | break; | 
|---|
| 202 | } | 
|---|
| 203 | handleVolume(); | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 207 | void AudioWidget::changeVolumeRegs() | 
|---|
| 208 | { | 
|---|
| 209 | int addr = myAudV->getSelectedAddr(); | 
|---|
| 210 | int value = myAudV->getSelectedValue(); | 
|---|
| 211 |  | 
|---|
| 212 | switch(addr) | 
|---|
| 213 | { | 
|---|
| 214 | case kAud0Addr: | 
|---|
| 215 | instance().debugger().tiaDebug().audV0(value); | 
|---|
| 216 | break; | 
|---|
| 217 |  | 
|---|
| 218 | case kAud1Addr: | 
|---|
| 219 | instance().debugger().tiaDebug().audV1(value); | 
|---|
| 220 | break; | 
|---|
| 221 | } | 
|---|
| 222 | handleVolume(); | 
|---|
| 223 | } | 
|---|
| 224 |  | 
|---|
| 225 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
|---|
| 226 | uInt32 AudioWidget::getEffectiveVolume() | 
|---|
| 227 | { | 
|---|
| 228 | const int EFF_VOL[] = { | 
|---|
| 229 | 0,  6, 13, 18, 24, 29, 33, 38, | 
|---|
| 230 | 42, 46, 50, 54, 57, 60, 64, 67, | 
|---|
| 231 | 70, 72, 75, 78, 80, 82, 85, 87, | 
|---|
| 232 | 89, 91, 93, 95, 97, 98,100}; | 
|---|
| 233 |  | 
|---|
| 234 | return EFF_VOL[(instance().debugger().tiaDebug().audC0() ? instance().debugger().tiaDebug().audV0() : 0) + | 
|---|
| 235 | (instance().debugger().tiaDebug().audC1() ? instance().debugger().tiaDebug().audV1() : 0)]; | 
|---|
| 236 | } | 
|---|
| 237 |  | 
|---|