Skip to content

Commit e3a718e

Browse files
committed
TIVarFile: call getMinVersionFromData handler and add some tests.
1 parent 195c76f commit e3a718e

File tree

3 files changed

+102
-3
lines changed

3 files changed

+102
-3
lines changed

src/TIVarFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ namespace tivars
223223
{
224224
entry.data_length2 = entry.data_length = (uint16_t) entry.data.size();
225225
this->header.entries_len += sizeof(var_entry_t::data_length) + sizeof(var_entry_t::data_length2) + entry.meta_length + entry.data_length;
226-
// todo: update entry version field
226+
entry.version = (this->calcModel.getFlags() & TIFeatureFlags::hasFlash) ? std::get<2>(entry._type.getHandlers())(entry.data) : 0;
227227
}
228228
this->computedChecksum = this->computeChecksumFromInstanceData();
229229
}

src/TypeHandlers/TH_Tokenized.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,56 @@ namespace tivars::TypeHandlers
216216

217217
uint8_t TH_Tokenized::getMinVersionFromData(const data_t& data)
218218
{
219-
(void)data;
220-
return 0;
219+
const size_t dataSize = data.size();
220+
if (dataSize < 2)
221+
{
222+
throw std::invalid_argument("Invalid data array. Needs to contain at least 2 bytes (size fields)");
223+
}
224+
225+
bool usesRTC = false;
226+
int maxBB = -1;
227+
int maxEF = -1;
228+
uint16_t offset = 2;
229+
while (offset < dataSize) {
230+
const uint8_t firstByte = data[offset++];
231+
if (is_in_vector(firstByteOfTwoByteTokens, firstByte)) {
232+
if (offset >= dataSize) {
233+
break;
234+
}
235+
uint8_t secondByte = data[offset++];
236+
if (firstByte == 0xBB) {
237+
if (secondByte > maxBB) maxBB = secondByte;
238+
} else if (firstByte == 0xEF) {
239+
if (secondByte <= 0x10) usesRTC = true;
240+
if (secondByte > maxEF) maxEF = secondByte;
241+
}
242+
}
243+
}
244+
uint8_t version = usesRTC ? 0x20 : 0x00;
245+
if (maxBB > 0xF5 || maxEF > 0xA6) {
246+
version = 0xFF;
247+
} else if (maxEF > 0x98) {
248+
version |= 0x0C;
249+
} else if (maxEF > 0x75) {
250+
version |= 0x0B;
251+
} else if (maxEF > 0x40) {
252+
version |= 0x0A;
253+
} else if (maxEF > 0x3E) {
254+
version |= 0x07;
255+
} else if (maxEF > 0x16) {
256+
version |= 0x06;
257+
} else if (maxEF > 0x12) {
258+
version |= 0x05;
259+
} else if (maxEF > -1) {
260+
version |= 0x04;
261+
} else if (maxBB > 0xDA) {
262+
version |= 0x03;
263+
} else if (maxBB > 0xCE) {
264+
version |= 0x02;
265+
} else if (maxBB > 0x67) {
266+
version |= 0x01;
267+
}
268+
return version;
221269
}
222270

223271
std::string TH_Tokenized::reindentCodeString(const std::string& str_orig, const options_t& options)

tests.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,57 @@ int main(int argc, char** argv)
6767
assert(trim(testPrgmStr1.getReadableContent({{"prettify", true}, {"reindent", true}})) == "\"42→Str1\nStr2\n123");
6868
}
6969

70+
{
71+
// See https://wikiti.brandonw.net/index.php?title=83Plus:OS:Variable_Versions
72+
TIVarFile testPrgmStr1 = TIVarFile::createNew("Program", "asdf");
73+
const auto& ver = testPrgmStr1.getVarEntries()[0].version;
74+
assert(ver == 0x00);
75+
testPrgmStr1.setContentFromString("Disp 41+1");
76+
assert((ver & ~0x20) == 0x00);
77+
testPrgmStr1.setContentFromString("Archive A");
78+
assert((ver & ~0x20) == 0x01);
79+
testPrgmStr1.setContentFromString("GarbageCollect");
80+
assert((ver & ~0x20) == 0x01);
81+
testPrgmStr1.setContentFromString("Disp 42%");
82+
assert((ver & ~0x20) == 0x02);
83+
testPrgmStr1.setContentFromString("~A");
84+
assert((ver & ~0x20) == 0x02);
85+
testPrgmStr1.setContentFromString("Disp \"\"");
86+
assert((ver & ~0x20) == 0x03);
87+
testPrgmStr1.setContentFromString("Disp \"\"");
88+
assert((ver & ~0x20) == 0x03);
89+
testPrgmStr1.setContentFromString("setDate(A,B,C)");
90+
assert((ver & ~0x20) == 0x04);
91+
testPrgmStr1.setContentFromString("ExecLib \"A\"");
92+
assert((ver & ~0x20) == 0x04);
93+
testPrgmStr1.setContentFromString("Manual-Fit ");
94+
assert((ver & ~0x20) == 0x05);
95+
testPrgmStr1.setContentFromString("ZQuadrant1");
96+
assert((ver & ~0x20) == 0x06);
97+
testPrgmStr1.setContentFromString("FRAC");
98+
assert((ver & ~0x20) == 0x06);
99+
testPrgmStr1.setContentFromString("STATWIZARD ON");
100+
assert((ver & ~0x20) == 0x07);
101+
testPrgmStr1.setContentFromString("STATWIZARD OFF");
102+
assert((ver & ~0x20) == 0x07);
103+
testPrgmStr1.setContentFromString("BLUE");
104+
assert((ver & ~0x20) == 0x0A);
105+
testPrgmStr1.setContentFromString("Dot-Thin");
106+
assert((ver & ~0x20) == 0x0A);
107+
testPrgmStr1.setContentFromString("TraceStep");
108+
assert((ver & ~0x20) == 0x00); // 63** token ranges are not considered by a calculator when it generates the version.
109+
testPrgmStr1.setContentFromString("Asm84CEPrgm:C9");
110+
assert((ver & ~0x20) == 0x0B);
111+
testPrgmStr1.setContentFromString("Disp eval(Str1");
112+
assert((ver & ~0x20) == 0x0B); // 0Bh is used for all of TI-84 Plus CE OS 5.0 through 5.2, despite tokens being added between them.
113+
testPrgmStr1.setContentFromString("Quartiles Setting…");
114+
assert((ver & ~0x20) == 0x0B);
115+
testPrgmStr1.setContentFromString("Execute Program");
116+
assert((ver & ~0x20) == 0x0C);
117+
testPrgmStr1.setContentFromString("piecewise(");
118+
assert((ver & ~0x20) == 0x0C);
119+
}
120+
70121
{
71122
assert(TH_Tokenized::oneTokenBytesToString(0x00) == "");
72123
assert(TH_Tokenized::oneTokenBytesToString(0xBB) == "");

0 commit comments

Comments
 (0)