Canola
0.8.D001
|
00001 // 00002 // canola - canon canola 1614p emulator 00003 // Copyright (C) 2011, 2012 Peter Miller 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License, version 3, as 00007 // published by the Free Software Foundation. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License along 00015 // with this program. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include <lib/calculator.h> 00019 #include <lib/program_card/functor.h> 00020 #include <lib/std_string_printf.h> 00021 #include <lib/sizeof.h> 00022 00023 00024 typedef std::list<int> int_list_t; 00025 00026 static void 00027 add_flag(int_list_t &flags, int flag) 00028 { 00029 int_list_t::iterator it = std::find(flags.begin(), flags.end(), flag); 00030 if (it == flags.end()) 00031 flags.push_back(flag); 00032 00033 } 00034 00035 00036 void 00037 calculator::program_card_walk(program_card_functor &f) 00038 const 00039 { 00040 f.set_title(get_property("title")); 00041 f.set_style(get_property("style")); // do this first so can override 00042 if (have_property("arrow")) 00043 f.set_arrow(get_bool_property("arrow")); 00044 if (have_property("color")) 00045 f.set_color(get_property("color")); 00046 if (have_property("disassemble")) 00047 f.set_disassemble(get_bool_property("disassemble")); 00048 if (have_property("perforations")) 00049 f.set_perforations(get_bool_property("perforations")); 00050 if (have_property("trim-corners")) 00051 f.set_trim_corners(get_bool_property("trim-corners")); 00052 00053 unsigned lo = 1; 00054 unsigned hi = 241; 00055 switch (program_selector) 00056 { 00057 case program_selector_i: 00058 hi = 121; 00059 break; 00060 00061 case program_selector_ii: 00062 lo = 121; 00063 break; 00064 00065 default: 00066 case program_selector_i_ii: 00067 break; 00068 } 00069 00070 // Stop at the first $000 instruction 00071 { 00072 unsigned max = lo; 00073 while (max < hi && programme[max]) 00074 ++max; 00075 hi = max; 00076 } 00077 f.set_steps(hi - lo); 00078 00079 // look for SFJ and FJ 00080 { 00081 int_list_t sfj_list; 00082 int_list_t fj_list; 00083 int_list_t memory_list; 00084 for (unsigned pc = lo; pc < hi; ++pc) 00085 { 00086 opcode_t op = (opcode_t)programme[pc]; 00087 assert(op < 128); 00088 switch (op) 00089 { 00090 case opcode_zero: 00091 case opcode_plus_equals: 00092 case opcode_minus_equals: 00093 case opcode_mul: 00094 case opcode_div: 00095 case opcode_sqrt: 00096 case opcode_ent: 00097 break; 00098 00099 case opcode_sj: 00100 case opcode_ej: 00101 case opcode_mj: 00102 case opcode_uj: 00103 case opcode_fj: 00104 add_flag(fj_list, programme[++pc]); 00105 break; 00106 00107 case opcode_suj: 00108 case opcode_sfj: 00109 add_flag(sfj_list, programme[++pc]); 00110 break; 00111 00112 case opcode_srj: 00113 break; 00114 00115 case opcode_m1: 00116 case opcode_m2: 00117 case opcode_m3: 00118 case opcode_m4: 00119 case opcode_m5: 00120 case opcode_m6: 00121 case opcode_m7: 00122 case opcode_m8: 00123 case opcode_m9: 00124 case opcode_m10: 00125 case opcode_m11: 00126 case opcode_m12: 00127 case opcode_m13: 00128 case opcode_m14: 00129 add_flag(memory_list, op - (opcode_m1 - 1)); 00130 break; 00131 00132 case opcode_mm1: 00133 case opcode_mm2: 00134 add_flag(memory_list, op - (opcode_mm1 - 1)); 00135 break; 00136 00137 case opcode_sm3: 00138 case opcode_sm4: 00139 case opcode_sm5: 00140 case opcode_sm6: 00141 case opcode_sm7: 00142 case opcode_sm8: 00143 case opcode_sm9: 00144 case opcode_sm10: 00145 case opcode_sm11: 00146 case opcode_sm12: 00147 case opcode_sm13: 00148 case opcode_sm14: 00149 add_flag(memory_list, op - (opcode_sm3 - 3)); 00150 break; 00151 00152 case opcode_rm1: 00153 case opcode_rm2: 00154 case opcode_rm3: 00155 case opcode_rm4: 00156 case opcode_rm5: 00157 case opcode_rm6: 00158 case opcode_rm7: 00159 case opcode_rm8: 00160 case opcode_rm9: 00161 case opcode_rm10: 00162 case opcode_rm11: 00163 case opcode_rm12: 00164 case opcode_rm13: 00165 case opcode_rm14: 00166 add_flag(memory_list, op - (opcode_rm1 - 1)); 00167 break; 00168 00169 case opcode_clear_indicator: 00170 break; 00171 00172 case opcode_cm1: 00173 case opcode_cm2: 00174 case opcode_cm3: 00175 case opcode_cm4: 00176 case opcode_cm5: 00177 case opcode_cm6: 00178 case opcode_cm7: 00179 case opcode_cm8: 00180 case opcode_cm9: 00181 case opcode_cm10: 00182 case opcode_cm11: 00183 case opcode_cm12: 00184 case opcode_cm13: 00185 case opcode_cm14: 00186 add_flag(memory_list, op - (opcode_cm1 - 1)); 00187 break; 00188 00189 case opcode_dot: 00190 case opcode_rv: 00191 case opcode_right: 00192 case opcode_chg_sign: 00193 break; 00194 00195 case opcode_round_down: 00196 case opcode_round_off: 00197 case opcode_round_up: 00198 ++pc; 00199 break; 00200 00201 case opcode_print: 00202 case opcode_fd: 00203 case opcode_n0: 00204 case opcode_n1: 00205 case opcode_n2: 00206 case opcode_n3: 00207 case opcode_n4: 00208 case opcode_n5: 00209 case opcode_n6: 00210 case opcode_n7: 00211 case opcode_n8: 00212 case opcode_n9: 00213 case opcode_n10: 00214 case opcode_n11: 00215 case opcode_n12: 00216 case opcode_n13: 00217 case opcode_n14: 00218 break; 00219 00220 case opcode_extended_c: 00221 case opcode_extended_start: 00222 case opcode_extended_m3_tilde: 00223 case opcode_extended_sm3_tilde: 00224 case opcode_extended_rm3_tilde: 00225 case opcode_extended_cm3_tilde: 00226 case opcode_extended_off: 00227 case opcode_extended_program_print: 00228 case opcode_extended_display_print: 00229 case opcode_extended_paper_feed: 00230 case opcode_extended_rounding_switch_up: 00231 case opcode_extended_rounding_switch_off: 00232 case opcode_extended_rounding_switch_down: 00233 case opcode_extended_decimal_point_selector_0: 00234 case opcode_extended_decimal_point_selector_1: 00235 case opcode_extended_decimal_point_selector_2: 00236 case opcode_extended_decimal_point_selector_3: 00237 case opcode_extended_decimal_point_selector_4: 00238 case opcode_extended_decimal_point_selector_5: 00239 case opcode_extended_decimal_point_selector_6: 00240 case opcode_extended_decimal_point_selector_7: 00241 case opcode_extended_decimal_point_selector_8: 00242 case opcode_extended_decimal_point_selector_9: 00243 case opcode_extended_decimal_point_selector_10: 00244 case opcode_extended_decimal_point_selector_11: 00245 case opcode_extended_decimal_point_selector_12: 00246 case opcode_extended_decimal_point_selector_float: 00247 case opcode_extended_goto_000: 00248 case opcode_extended_goto_001: 00249 case opcode_extended_goto_002: 00250 case opcode_extended_goto_003: 00251 case opcode_extended_goto_004: 00252 case opcode_extended_goto_005: 00253 case opcode_extended_goto_006: 00254 case opcode_extended_goto_007: 00255 case opcode_extended_goto_008: 00256 case opcode_extended_goto_009: 00257 case opcode_extended_goto_010: 00258 case opcode_extended_goto_011: 00259 case opcode_extended_goto_012: 00260 case opcode_extended_goto_013: 00261 case opcode_extended_goto_014: 00262 case opcode_extended_goto_015: 00263 case opcode_extended_goto_100: 00264 case opcode_extended_goto_101: 00265 case opcode_extended_goto_102: 00266 case opcode_extended_goto_103: 00267 case opcode_extended_goto_104: 00268 case opcode_extended_goto_105: 00269 case opcode_extended_goto_106: 00270 case opcode_extended_goto_107: 00271 case opcode_extended_goto_108: 00272 case opcode_extended_goto_109: 00273 case opcode_extended_goto_110: 00274 case opcode_extended_goto_111: 00275 case opcode_extended_goto_112: 00276 case opcode_extended_goto_113: 00277 case opcode_extended_goto_114: 00278 case opcode_extended_goto_115: 00279 case opcode_extended_goto_200: 00280 case opcode_extended_goto_201: 00281 case opcode_extended_goto_202: 00282 case opcode_extended_goto_203: 00283 case opcode_extended_goto_204: 00284 case opcode_extended_goto_205: 00285 case opcode_extended_goto_206: 00286 case opcode_extended_goto_207: 00287 case opcode_extended_goto_208: 00288 case opcode_extended_goto_209: 00289 case opcode_extended_goto_210: 00290 case opcode_extended_goto_211: 00291 case opcode_extended_goto_212: 00292 case opcode_extended_goto_213: 00293 case opcode_extended_goto_214: 00294 case opcode_extended_goto_215: 00295 case opcode_extended_goto_300: 00296 case opcode_extended_goto_301: 00297 case opcode_extended_goto_302: 00298 case opcode_extended_goto_303: 00299 case opcode_extended_goto_304: 00300 case opcode_extended_goto_305: 00301 case opcode_extended_goto_306: 00302 case opcode_extended_goto_307: 00303 case opcode_extended_goto_308: 00304 case opcode_extended_goto_309: 00305 case opcode_extended_goto_310: 00306 case opcode_extended_goto_311: 00307 case opcode_extended_goto_312: 00308 case opcode_extended_goto_313: 00309 case opcode_extended_goto_314: 00310 case opcode_extended_goto_315: 00311 case opcode_extended_goto_400: 00312 case opcode_extended_goto_401: 00313 case opcode_extended_goto_402: 00314 case opcode_extended_goto_403: 00315 case opcode_extended_goto_404: 00316 case opcode_extended_goto_405: 00317 case opcode_extended_goto_406: 00318 case opcode_extended_goto_407: 00319 case opcode_extended_goto_408: 00320 case opcode_extended_goto_409: 00321 case opcode_extended_goto_410: 00322 case opcode_extended_goto_411: 00323 case opcode_extended_goto_412: 00324 case opcode_extended_goto_413: 00325 case opcode_extended_goto_414: 00326 case opcode_extended_goto_415: 00327 case opcode_extended_goto_500: 00328 case opcode_extended_goto_501: 00329 case opcode_extended_goto_502: 00330 case opcode_extended_goto_503: 00331 case opcode_extended_goto_504: 00332 case opcode_extended_goto_505: 00333 case opcode_extended_goto_506: 00334 case opcode_extended_goto_507: 00335 case opcode_extended_goto_508: 00336 case opcode_extended_goto_509: 00337 case opcode_extended_goto_510: 00338 case opcode_extended_goto_511: 00339 case opcode_extended_goto_512: 00340 case opcode_extended_goto_513: 00341 case opcode_extended_goto_514: 00342 case opcode_extended_goto_515: 00343 case opcode_extended_goto_600: 00344 case opcode_extended_goto_601: 00345 case opcode_extended_goto_602: 00346 case opcode_extended_goto_603: 00347 case opcode_extended_goto_604: 00348 case opcode_extended_goto_605: 00349 case opcode_extended_goto_606: 00350 case opcode_extended_goto_607: 00351 case opcode_extended_goto_608: 00352 case opcode_extended_goto_609: 00353 case opcode_extended_goto_610: 00354 case opcode_extended_goto_611: 00355 case opcode_extended_goto_612: 00356 case opcode_extended_goto_613: 00357 case opcode_extended_goto_614: 00358 case opcode_extended_goto_615: 00359 case opcode_extended_goto_700: 00360 case opcode_extended_goto_701: 00361 case opcode_extended_goto_702: 00362 case opcode_extended_goto_703: 00363 case opcode_extended_goto_704: 00364 case opcode_extended_goto_705: 00365 case opcode_extended_goto_706: 00366 case opcode_extended_goto_707: 00367 case opcode_extended_goto_708: 00368 case opcode_extended_goto_709: 00369 case opcode_extended_goto_710: 00370 case opcode_extended_goto_711: 00371 case opcode_extended_goto_712: 00372 case opcode_extended_goto_713: 00373 case opcode_extended_goto_714: 00374 case opcode_extended_goto_715: 00375 break; 00376 00377 default: 00378 break; 00379 } 00380 } 00381 if (!sfj_list.empty()) 00382 { 00383 sfj_list.sort(); 00384 std::string text; 00385 bool first = true; 00386 for 00387 ( 00388 int_list_t::const_iterator it = sfj_list.begin(); 00389 it != sfj_list.end(); 00390 ++it 00391 ) 00392 { 00393 if (first) 00394 first = false; 00395 else 00396 text += ", "; 00397 text += opcode_raw_name((opcode_t)*it); 00398 } 00399 f.set_sfj_list(text); 00400 } 00401 if (!fj_list.empty()) 00402 { 00403 fj_list.sort(); 00404 std::string text; 00405 bool first = true; 00406 for 00407 ( 00408 int_list_t::const_iterator it = fj_list.begin(); 00409 it != fj_list.end(); 00410 ++it 00411 ) 00412 { 00413 if (first) 00414 first = false; 00415 else 00416 text += ", "; 00417 text += opcode_raw_name((opcode_t)*it); 00418 } 00419 f.set_fj_list(text); 00420 } 00421 if (!memory_list.empty()) 00422 { 00423 memory_list.sort(); 00424 std::string text; 00425 bool first = true; 00426 for 00427 ( 00428 int_list_t::const_iterator it = memory_list.begin(); 00429 it != memory_list.end(); 00430 ++it 00431 ) 00432 { 00433 if (first) 00434 first = false; 00435 else 00436 text += ", "; 00437 text += std_string_printf("%d", *it); 00438 } 00439 f.set_memory_list(text); 00440 } 00441 } 00442 00443 unsigned ipc = f.instructions_per_card(); 00444 assert(ipc > 0); 00445 00446 unsigned card_count = (hi - lo + ipc - 1) / ipc; 00447 for (unsigned card_num = 1; card_num <= card_count; ++card_num) 00448 { 00449 unsigned start = lo + ipc * (card_num - 1); 00450 unsigned finish = start + ipc; 00451 if (finish > hi) 00452 finish = hi; 00453 f(card_num, card_count, programme + start, finish - start); 00454 } 00455 } 00456 00457 00458 bool 00459 calculator::have_property(const std::string &name) 00460 const 00461 { 00462 properties_t::const_iterator it = properties.find(name); 00463 return (it != properties.end()); 00464 } 00465 00466 00467 std::string 00468 calculator::get_property(const std::string &name, const std::string &dflt) 00469 const 00470 { 00471 properties_t::const_iterator it = properties.find(name); 00472 if (it == properties.end()) 00473 return dflt; 00474 return it->second; 00475 } 00476 00477 00478 bool 00479 calculator::get_bool_property(const std::string &name, bool dflt) 00480 const 00481 { 00482 properties_t::const_iterator it = properties.find(name); 00483 if (it == properties.end()) 00484 return dflt; 00485 00486 struct table_t 00487 { 00488 const char *name; 00489 bool value; 00490 }; 00491 00492 static const table_t table[] = 00493 { 00494 { "true", true }, 00495 { "false", false }, 00496 { "yes", true }, 00497 { "no", false }, 00498 { "1", true }, 00499 { "0", false }, 00500 }; 00501 00502 for (const table_t *tp = table; tp < ENDOF(table); ++tp) 00503 { 00504 if (it->second == tp->name) 00505 return tp->value; 00506 } 00507 return dflt; 00508 }