00001
00002
00003
00004
00005
00006
00007 #include "sysdeps.h"
00008
00009 #include "SAM.h"
00010 #include "C64.h"
00011 #include "CPUC64.h"
00012 #include "CPU1541.h"
00013 #include "VIC.h"
00014 #include "SID.h"
00015 #include "CIA.h"
00016
00017
00018
00019 static MOS6510 *TheCPU;
00020 static MOS6502_1541 *TheCPU1541;
00021 static MOS6569 *TheVIC;
00022 static MOS6581 *TheSID;
00023 static MOS6526_1 *TheCIA1;
00024 static MOS6526_2 *TheCIA2;
00025
00026
00027 static MOS6510State R64;
00028 static MOS6502State R1541;
00029
00030 static bool access_1541;
00031
00032
00033 static inline uint8 SAMReadByte(uint16 adr)
00034 {
00035 if (access_1541)
00036 return TheCPU1541->ExtReadByte(adr);
00037 else
00038 return TheCPU->ExtReadByte(adr);
00039 }
00040
00041 static inline void SAMWriteByte(uint16 adr, uint8 byte)
00042 {
00043 if (access_1541)
00044 TheCPU1541->ExtWriteByte(adr, byte);
00045 else
00046 TheCPU->ExtWriteByte(adr, byte);
00047 }
00048
00049
00050
00051 static FILE *fin, *fout, *ferr;
00052
00053
00054 #define INPUT_LENGTH 80
00055 static char input[INPUT_LENGTH];
00056 static char *in_ptr;
00057
00058 static uint16 address, end_address;
00059
00060
00061
00062 enum Token {
00063 T_NULL,
00064 T_END,
00065 T_NUMBER,
00066 T_STRING,
00067 T_LPAREN,
00068 T_RPAREN,
00069 T_ADD,
00070 T_SUB,
00071 T_MUL,
00072 T_DIV,
00073 T_COMMA,
00074 T_IMMED,
00075 T_X,
00076 T_Y,
00077 T_PC,
00078 T_SP,
00079
00080 T_A,
00081 T_DR,
00082 T_PR
00083 };
00084
00085 static enum Token the_token;
00086 static uint16 the_number;
00087 static char the_string[INPUT_LENGTH];
00088
00089
00090
00091 enum {
00092 A_IMPL,
00093 A_ACCU,
00094 A_IMM,
00095 A_REL,
00096 A_ZERO,
00097 A_ZEROX,
00098 A_ZEROY,
00099 A_ABS,
00100 A_ABSX,
00101 A_ABSY,
00102 A_IND,
00103 A_INDX,
00104 A_INDY
00105 };
00106
00107
00108 enum {
00109 M_ADC, M_AND, M_ASL, M_BCC, M_BCS, M_BEQ, M_BIT, M_BMI, M_BNE, M_BPL,
00110 M_BRK, M_BVC, M_BVS, M_CLC, M_CLD, M_CLI, M_CLV, M_CMP, M_CPX, M_CPY,
00111 M_DEC, M_DEX, M_DEY, M_EOR, M_INC, M_INX, M_INY, M_JMP, M_JSR, M_LDA,
00112 M_LDX, M_LDY, M_LSR, M_NOP, M_ORA, M_PHA, M_PHP, M_PLA, M_PLP, M_ROL,
00113 M_ROR, M_RTI, M_RTS, M_SBC, M_SEC, M_SED, M_SEI, M_STA, M_STX, M_STY,
00114 M_TAX, M_TAY, M_TSX, M_TXA, M_TXS, M_TYA,
00115
00116 M_ILLEGAL,
00117
00118 M_IANC, M_IANE, M_IARR, M_IASR, M_IDCP, M_IISB, M_IJAM, M_INOP, M_ILAS,
00119 M_ILAX, M_ILXA, M_IRLA, M_IRRA, M_ISAX, M_ISBC, M_ISBX, M_ISHA, M_ISHS,
00120 M_ISHX, M_ISHY, M_ISLO, M_ISRE,
00121
00122 M_MAXIMUM
00123 };
00124
00125
00126 static const char mnemonic[256] = {
00127 M_BRK , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO,
00128 M_PHP , M_ORA , M_ASL , M_IANC, M_INOP, M_ORA, M_ASL , M_ISLO,
00129 M_BPL , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO,
00130 M_CLC , M_ORA , M_INOP, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO,
00131 M_JSR , M_AND , M_IJAM, M_IRLA, M_BIT , M_AND, M_ROL , M_IRLA,
00132 M_PLP , M_AND , M_ROL , M_IANC, M_BIT , M_AND, M_ROL , M_IRLA,
00133 M_BMI , M_AND , M_IJAM, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA,
00134 M_SEC , M_AND , M_INOP, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA,
00135 M_RTI , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE,
00136 M_PHA , M_EOR , M_LSR , M_IASR, M_JMP , M_EOR, M_LSR , M_ISRE,
00137 M_BVC , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE,
00138 M_CLI , M_EOR , M_INOP, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE,
00139 M_RTS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA,
00140 M_PLA , M_ADC , M_ROR , M_IARR, M_JMP , M_ADC, M_ROR , M_IRRA,
00141 M_BVS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA,
00142 M_SEI , M_ADC , M_INOP, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA,
00143 M_INOP, M_STA , M_INOP, M_ISAX, M_STY , M_STA, M_STX , M_ISAX,
00144 M_DEY , M_INOP, M_TXA , M_IANE, M_STY , M_STA, M_STX , M_ISAX,
00145 M_BCC , M_STA , M_IJAM, M_ISHA, M_STY , M_STA, M_STX , M_ISAX,
00146 M_TYA , M_STA , M_TXS , M_ISHS, M_ISHY, M_STA, M_ISHX, M_ISHA,
00147 M_LDY , M_LDA , M_LDX , M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX,
00148 M_TAY , M_LDA , M_TAX , M_ILXA, M_LDY , M_LDA, M_LDX , M_ILAX,
00149 M_BCS , M_LDA , M_IJAM, M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX,
00150 M_CLV , M_LDA , M_TSX , M_ILAS, M_LDY , M_LDA, M_LDX , M_ILAX,
00151 M_CPY , M_CMP , M_INOP, M_IDCP, M_CPY , M_CMP, M_DEC , M_IDCP,
00152 M_INY , M_CMP , M_DEX , M_ISBX, M_CPY , M_CMP, M_DEC , M_IDCP,
00153 M_BNE , M_CMP , M_IJAM, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP,
00154 M_CLD , M_CMP , M_INOP, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP,
00155 M_CPX , M_SBC , M_INOP, M_IISB, M_CPX , M_SBC, M_INC , M_IISB,
00156 M_INX , M_SBC , M_NOP , M_ISBC, M_CPX , M_SBC, M_INC , M_IISB,
00157 M_BEQ , M_SBC , M_IJAM, M_IISB, M_INOP, M_SBC, M_INC , M_IISB,
00158 M_SED , M_SBC , M_INOP, M_IISB, M_INOP, M_SBC, M_INC , M_IISB
00159 };
00160
00161
00162 static const char adr_mode[256] = {
00163 A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00164 A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
00165 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX,
00166 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
00167 A_ABS , A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00168 A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
00169 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX,
00170 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
00171 A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00172 A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
00173 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX,
00174 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
00175 A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00176 A_IMPL, A_IMM , A_ACCU, A_IMM , A_IND , A_ABS , A_ABS , A_ABS,
00177 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX,
00178 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
00179 A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00180 A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
00181 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY,
00182 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY,
00183 A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00184 A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
00185 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY,
00186 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY,
00187 A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00188 A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
00189 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX,
00190 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
00191 A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,
00192 A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
00193 A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX,
00194 A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX
00195 };
00196
00197
00198 static const char mnem_1[] = "aaabbbbbbbbbbcccccccdddeiiijjllllnopppprrrrssssssstttttt?aaaadijnlllrrsssssssss";
00199 static const char mnem_2[] = "dnscceimnprvvllllmppeeeonnnmsdddsorhhlloottbeeetttaasxxy?nnrscsaoaaxlrabbhhhhlr";
00200 static const char mnem_3[] = "cdlcsqtielkcscdivpxycxyrcxypraxyrpaapaplrisccdiaxyxyxasa?cerrpbmpsxaaaxcxasxyoe";
00201
00202
00203 static const char adr_length[] = {1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2};
00204
00205
00206
00207 static void error(char *s);
00208 static void handle_abort(int);
00209 static void init_abort(void);
00210 static void exit_abort(void);
00211 static bool aborted(void);
00212
00213 static void read_line(void);
00214 static char get_char(void);
00215 static void put_back(char c);
00216 static enum Token get_token(void);
00217 static enum Token get_reg_token(void);
00218 static uint16 get_number(void);
00219 static enum Token get_string(char *str);
00220
00221 static bool expression(uint16 *number);
00222 static bool term(uint16 *number);
00223 static bool factor(uint16 *number);
00224 static bool address_args(void);
00225 static bool range_args(int def_range);
00226 static bool instr_args(uint16 *number, char *mode);
00227
00228 static void help(void);
00229 static void registers(void);
00230 static void display_registers(void);
00231 static void memory_dump(void);
00232 static void ascii_dump(void);
00233 static char conv_from_64(char c);
00234 static void screen_dump(void);
00235 static char conv_from_scode(char c);
00236 static void binary_dump(void);
00237 static void sprite_dump(void);
00238 static void byte_to_bin(uint8 byte, char *str);
00239 static void disassemble(void);
00240 static int disass_line(uint16 adr, uint8 op, uint8 lo, uint8 hi);
00241 static void assemble(void);
00242 static char find_mnemonic(char op1, char op2, char op3);
00243 static bool find_opcode(char mnem, char mode, uint8 *opcode);
00244 static void mem_config(void);
00245 static void fill(void);
00246 static void compare(void);
00247 static void transfer(void);
00248 static void modify(void);
00249 static void print_expr(void);
00250 static void redir_output(void);
00251 static void int_vectors(void);
00252 static void view_state(void);
00253 static void view_cia_state(void);
00254 static void dump_cia_ints(uint8 i);
00255 static void view_sid_state(void);
00256 static void dump_sid_waveform(uint8 wave);
00257 static void view_vic_state(void);
00258 static void dump_spr_flags(uint8 f);
00259 static void dump_vic_ints(uint8 i);
00260 static void view_1541_state(void);
00261 static void dump_via_ints(uint8 i);
00262 static void load_data(void);
00263 static void save_data(void);
00264
00265
00266
00267
00268
00269
00270 void SAM(C64 *the_c64)
00271 {
00272 bool done = false;
00273 char c;
00274
00275 TheCPU = the_c64->TheCPU;
00276 TheCPU1541 = the_c64->TheCPU1541;
00277 TheVIC = the_c64->TheVIC;
00278 TheSID = the_c64->TheSID;
00279 TheCIA1 = the_c64->TheCIA1;
00280 TheCIA2 = the_c64->TheCIA2;
00281
00282
00283 TheCPU->GetState(&R64);
00284 TheCPU->ExtConfig = (~R64.ddr | R64.pr) & 7;
00285 TheCPU1541->GetState(&R1541);
00286
00287 #ifdef __riscos__
00288 Wimp_CommandWindow((int)"SAM");
00289 #endif
00290
00291 #ifdef AMIGA
00292 if (!(fin = fout = ferr = fopen("CON:0/0/640/480/SAM", "w+")))
00293 return;
00294 #else
00295 fin = stdin;
00296 fout = stdout;
00297 ferr = stdout;
00298 #endif
00299
00300 access_1541 = false;
00301 address = R64.pc;
00302
00303 fprintf(ferr, "\n *** SAM - Simple Assembler and Monitor ***\n *** Press 'h' for help ***\n\n");
00304 init_abort();
00305 display_registers();
00306
00307 while (!done) {
00308 if (access_1541)
00309 fprintf(ferr, "1541> ");
00310 else
00311 fprintf(ferr, "C64> ");
00312 fflush(ferr);
00313 read_line();
00314 while ((c = get_char()) == ' ') ;
00315
00316 switch (c) {
00317 case 'a':
00318 get_token();
00319 assemble();
00320 break;
00321
00322 case 'b':
00323 get_token();
00324 binary_dump();
00325 break;
00326
00327 case 'c':
00328 get_token();
00329 compare();
00330 break;
00331
00332 case 'd':
00333 get_token();
00334 disassemble();
00335 break;
00336
00337 case 'e':
00338 int_vectors();
00339 break;
00340
00341 case 'f':
00342 get_token();
00343 fill();
00344 break;
00345
00346 case 'h':
00347 help();
00348 break;
00349
00350 case 'i':
00351 get_token();
00352 ascii_dump();
00353 break;
00354
00355 case 'k':
00356 get_token();
00357 mem_config();
00358 break;
00359
00360 case 'l':
00361 get_token();
00362 load_data();
00363 break;
00364
00365 case 'm':
00366 get_token();
00367 memory_dump();
00368 break;
00369
00370 case 'n':
00371 get_token();
00372 screen_dump();
00373 break;
00374
00375 case 'o':
00376 get_token();
00377 redir_output();
00378 break;
00379
00380 case 'p':
00381 get_token();
00382 sprite_dump();
00383 break;
00384
00385 case 'r':
00386 get_reg_token();
00387 registers();
00388 break;
00389
00390 case 's':
00391 get_token();
00392 save_data();
00393 break;
00394
00395 case 't':
00396 get_token();
00397 transfer();
00398 break;
00399
00400 case 'v':
00401 view_state();
00402 break;
00403
00404 case 'x':
00405 done = true;
00406 break;
00407
00408 case ':':
00409 get_token();
00410 modify();
00411 break;
00412
00413 case '1':
00414 access_1541 = true;
00415 break;
00416
00417 case '6':
00418 access_1541 = false;
00419 break;
00420
00421 case '?':
00422 get_token();
00423 print_expr();
00424 break;
00425
00426 case '\n':
00427 break;
00428
00429 default:
00430 error("Unknown command");
00431 break;
00432 }
00433 }
00434
00435 exit_abort();
00436
00437 #ifdef AMIGA
00438 fclose(fin);
00439 #endif
00440 if (fout != ferr)
00441 fclose(fout);
00442
00443 #ifdef __riscos__
00444 Wimp_CommandWindow(-1);
00445 #endif
00446
00447
00448 TheCPU->SetState(&R64);
00449 TheCPU1541->SetState(&R1541);
00450 }
00451
00452
00453
00454
00455
00456
00457 static void error(char *s)
00458 {
00459 fprintf(ferr, "*** %s\n", s);
00460 }
00461
00462
00463
00464
00465
00466
00467 static bool WasAborted;
00468
00469 #ifdef HAVE_SIGACTION
00470 struct sigaction my_sa;
00471 #endif
00472
00473 static void handle_abort(int)
00474 {
00475 WasAborted = true;
00476 #if !defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL)
00477 #ifdef __riscos__
00478 signal(SIGINT, (Handler*) handle_abort);
00479 #else
00480 signal(SIGINT, (sighandler_t) handle_abort);
00481 #endif
00482 #endif
00483 }
00484
00485
00486 static void init_abort(void)
00487 {
00488 WasAborted = false;
00489 #if defined(HAVE_SIGACTION)
00490 my_sa.sa_handler = handle_abort;
00491 my_sa.sa_flags = 0;
00492 sigemptyset(&my_sa.sa_mask);
00493 sigaction(SIGINT, &my_sa, NULL);
00494 #elif defined(HAVE_SIGNAL)
00495 #ifdef __riscos__
00496 signal(SIGINT, (Handler*) handle_abort);
00497 #else
00498 signal(SIGINT, (sighandler_t) handle_abort);
00499 #endif
00500 #endif
00501 }
00502
00503 static void exit_abort(void)
00504 {
00505 #if defined(HAVE_SIGACTION)
00506 my_sa.sa_handler = SIG_DFL;
00507 sigaction(SIGINT, &my_sa, NULL);
00508 #elif defined(HAVE_SIGNAL)
00509 signal(SIGINT, SIG_DFL);
00510 #endif
00511 }
00512
00513 static bool aborted(void)
00514 {
00515 bool ret = WasAborted;
00516
00517 WasAborted = false;
00518 return ret;
00519 }
00520
00521
00522
00523
00524
00525
00526 static void read_line(void)
00527 {
00528 #ifdef __riscos__
00529 OS_ReadLine(in_ptr = input, INPUT_LENGTH, 0, 255, 0);
00530 #else
00531 fgets(in_ptr = input, INPUT_LENGTH, fin);
00532 #endif
00533 }
00534
00535
00536
00537
00538
00539
00540 static char get_char(void)
00541 {
00542 return *in_ptr++;
00543 }
00544
00545
00546
00547
00548
00549
00550 static void put_back(char c)
00551 {
00552 *(--in_ptr) = c;
00553 }
00554
00555
00556
00557
00558
00559
00560 static enum Token get_token(void)
00561 {
00562 char c;
00563
00564
00565 while ((c = get_char()) == ' ') ;
00566
00567 switch (c) {
00568 case '\n':
00569 return the_token = T_END;
00570 case '(':
00571 return the_token = T_LPAREN;
00572 case ')':
00573 return the_token = T_RPAREN;
00574 case '+':
00575 return the_token = T_ADD;
00576 case '-':
00577 return the_token = T_SUB;
00578 case '*':
00579 return the_token = T_MUL;
00580 case '/':
00581 return the_token = T_DIV;
00582 case ',':
00583 return the_token = T_COMMA;
00584 case '#':
00585 return the_token = T_IMMED;
00586 case 'x':
00587 return the_token = T_X;
00588 case 'y':
00589 return the_token = T_Y;
00590 case 'p':
00591 if (get_char() == 'c')
00592 return the_token = T_PC;
00593 else {
00594 error("Unrecognized token");
00595 return the_token = T_NULL;
00596 }
00597 case 's':
00598 if (get_char() == 'p')
00599 return the_token = T_SP;
00600 else {
00601 error("Unrecognized token");
00602 return the_token = T_NULL;
00603 }
00604 case '0': case '1': case '2': case '3': case '4':
00605 case '5': case '6': case '7': case '8': case '9':
00606 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
00607 put_back(c);
00608 the_number = get_number();
00609 return the_token = T_NUMBER;
00610 case '"':
00611 return the_token = get_string(the_string);
00612 default:
00613 error("Unrecognized token");
00614 return the_token = T_NULL;
00615 }
00616 }
00617
00618 static enum Token get_reg_token(void)
00619 {
00620 char c;
00621
00622
00623 while ((c = get_char()) == ' ') ;
00624
00625 switch (c) {
00626 case '\n':
00627 return the_token = T_END;
00628 case 'a':
00629 return the_token = T_A;
00630 case 'd':
00631 if (get_char() == 'r')
00632 return the_token = T_DR;
00633 else {
00634 error("Unrecognized token");
00635 return the_token = T_NULL;
00636 }
00637 case 'p':
00638 if ((c = get_char()) == 'c')
00639 return the_token = T_PC;
00640 else if (c == 'r')
00641 return the_token = T_PR;
00642 else {
00643 error("Unrecognized token");
00644 return the_token = T_NULL;
00645 }
00646 case 's':
00647 if (get_char() == 'p')
00648 return the_token = T_SP;
00649 else {
00650 error("Unrecognized token");
00651 return the_token = T_NULL;
00652 }
00653 case 'x':
00654 return the_token = T_X;
00655 case 'y':
00656 return the_token = T_Y;
00657 default:
00658 error("Unrecognized token");
00659 return the_token = T_NULL;
00660 }
00661 }
00662
00663 static uint16 get_number(void)
00664 {
00665 char c;
00666 uint16 i = 0;
00667
00668 while (((c = get_char()) >= '0') && (c <= '9') || (c >= 'a') && (c <= 'f'))
00669 if (c < 'a')
00670 i = (i << 4) + (c - '0');
00671 else
00672 i = (i << 4) + (c - 'a' + 10);
00673
00674 put_back(c);
00675 return i;
00676 }
00677
00678 static enum Token get_string(char *str)
00679 {
00680 char c;
00681
00682 while ((c = get_char()) != '\n') {
00683 if (c == '"') {
00684 *str = 0;
00685 return T_STRING;
00686 }
00687 *str++ = c;
00688 }
00689
00690 error("Unterminated string");
00691 return T_NULL;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700 static bool expression(uint16 *number)
00701 {
00702 uint16 accu, trm;
00703
00704 if (!term(&accu))
00705 return false;
00706
00707 for (;;)
00708 switch (the_token) {
00709 case T_ADD:
00710 get_token();
00711 if (!term(&trm))
00712 return false;
00713 accu += trm;
00714 break;
00715
00716 case T_SUB:
00717 get_token();
00718 if (!term(&trm))
00719 return false;
00720 accu -= trm;
00721 break;
00722
00723 default:
00724 *number = accu;
00725 return true;
00726 }
00727 }
00728
00729
00730
00731
00732
00733
00734
00735 static bool term(uint16 *number)
00736 {
00737 uint16 accu, fact;
00738
00739 if (!factor(&accu))
00740 return false;
00741
00742 for (;;)
00743 switch (the_token) {
00744 case T_MUL:
00745 get_token();
00746 if (!factor(&fact))
00747 return false;
00748 accu *= fact;
00749 break;
00750
00751 case T_DIV:
00752 get_token();
00753 if (!factor(&fact))
00754 return false;
00755 if (fact == 0) {
00756 error("Division by 0");
00757 return false;
00758 }
00759 accu /= fact;
00760 break;
00761
00762 default:
00763 *number = accu;
00764 return true;
00765 }
00766 }
00767
00768
00769
00770
00771
00772
00773
00774 static bool factor(uint16 *number)
00775 {
00776 switch (the_token) {
00777 case T_NUMBER:
00778 *number = the_number;
00779 get_token();
00780 return true;
00781
00782 case T_PC:
00783 get_token();
00784 *number = access_1541 ? R1541.pc : R64.pc;
00785 return true;
00786
00787 case T_SP:
00788 get_token();
00789 *number = access_1541 ? R1541.sp : R64.sp;
00790 return true;
00791
00792 case T_LPAREN:
00793 get_token();
00794 if (expression(number))
00795 if (the_token == T_RPAREN) {
00796 get_token();
00797 return true;
00798 } else {
00799 error("Missing ')'");
00800 return false;
00801 }
00802 else {
00803 error("Error in expression");
00804 return false;
00805 }
00806
00807 case T_END:
00808 error("Required argument missing");
00809 return false;
00810
00811 default:
00812 error("'pc', 'sp', '(' or number expected");
00813 return false;
00814 }
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 static bool address_args(void)
00827 {
00828 if (the_token == T_END)
00829 return true;
00830 else {
00831 if (!expression(&address))
00832 return false;
00833 return the_token == T_END;
00834 }
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 static bool range_args(int def_range)
00847 {
00848 end_address = address + def_range;
00849
00850 if (the_token == T_END)
00851 return true;
00852 else {
00853 if (!expression(&address))
00854 return false;
00855 end_address = address + def_range;
00856 if (the_token == T_END)
00857 return true;
00858 else {
00859 if (the_token == T_COMMA) get_token();
00860 if (!expression(&end_address))
00861 return false;
00862 return the_token == T_END;
00863 }
00864 }
00865 }
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 static bool instr_args(uint16 *number, char *mode)
00880 {
00881 switch (the_token) {
00882
00883 case T_END:
00884 *mode = A_IMPL;
00885 return true;
00886
00887 case T_IMMED:
00888 get_token();
00889 if (the_token == T_NUMBER) {
00890 *number = the_number;
00891 *mode = A_IMM;
00892 get_token();
00893 return the_token == T_END;
00894 } else {
00895 error("Number expected");
00896 return false;
00897 }
00898
00899 case T_NUMBER:
00900 *number = the_number;
00901 get_token();
00902 switch (the_token) {
00903
00904 case T_END:
00905 if (*number < 0x100)
00906 *mode = A_ZERO;
00907 else
00908 *mode = A_ABS;
00909 return true;
00910
00911 case T_COMMA:
00912 get_token();
00913 switch (the_token) {
00914
00915 case T_X:
00916 get_token();
00917 if (*number < 0x100)
00918 *mode = A_ZEROX;
00919 else
00920 *mode = A_ABSX;
00921 return the_token == T_END;
00922
00923 case T_Y:
00924 get_token();
00925 if (*number < 0x100)
00926 *mode = A_ZEROY;
00927 else
00928 *mode = A_ABSY;
00929 return the_token == T_END;
00930
00931 default:
00932 error("Illegal index register");
00933 return false;
00934 }
00935
00936 default:
00937 return false;
00938 }
00939
00940 case T_LPAREN:
00941 get_token();
00942 if (the_token == T_NUMBER) {
00943 *number = the_number;
00944 get_token();
00945 switch (the_token) {
00946
00947 case T_RPAREN:
00948 get_token();
00949 switch (the_token) {
00950
00951 case T_END:
00952 *mode = A_IND;
00953 return true;
00954
00955 case T_COMMA:
00956 get_token();
00957 if (the_token == T_Y) {
00958 *mode = A_INDY;
00959 get_token();
00960 return the_token == T_END;
00961 } else {
00962 error("Only 'y' index register allowed");
00963 return false;
00964 }
00965
00966 default:
00967 error("Illegal characters after ')'");
00968 return false;
00969 }
00970
00971 case T_COMMA:
00972 get_token();
00973 if (the_token == T_X) {
00974 get_token();
00975 if (the_token == T_RPAREN) {
00976 *mode = A_INDX;
00977 get_token();
00978 return the_token == T_END;
00979 } else {
00980 error("')' expected");
00981 return false;
00982 }
00983 } else {
00984 error("Only 'x' index register allowed");
00985 return false;
00986 }
00987
00988 default:
00989 error("')' or ',' expected");
00990 return false;
00991 }
00992 } else {
00993 error("Number expected");
00994 return false;
00995 }
00996
00997 default:
00998 error("'(', '#' or number expected");
00999 return false;
01000 }
01001 }
01002
01003
01004
01005
01006
01007
01008
01009 static void help(void)
01010 {
01011 fprintf(fout, "a [start] Assemble\n"
01012 "b [start] [end] Binary dump\n"
01013 "c start end dest Compare memory\n"
01014 "d [start] [end] Disassemble\n"
01015 "e Show interrupt vectors\n"
01016 "f start end byte Fill memory\n"
01017 "i [start] [end] ASCII/PETSCII dump\n"
01018 "k [config] Show/set C64 memory configuration\n"
01019 "l start \"file\" Load data\n"
01020 "m [start] [end] Memory dump\n"
01021 "n [start] [end] Screen code dump\n"
01022 "o [\"file\"] Redirect output\n"
01023 "p [start] [end] Sprite dump\n"
01024 "r [reg value] Show/set CPU registers\n"
01025 "s start end \"file\" Save data\n"
01026 "t start end dest Transfer memory\n"
01027 "vc1 View CIA 1 state\n"
01028 "vc2 View CIA 2 state\n"
01029 "vf View 1541 state\n"
01030 "vs View SID state\n"
01031 "vv View VIC state\n"
01032 "x Return to Frodo\n"
01033 ": addr {byte} Modify memory\n"
01034 "1541 Switch to 1541\n"
01035 "64 Switch to C64\n"
01036 "? expression Calculate expression\n");
01037 }
01038
01039
01040
01041
01042
01043
01044
01045 static void registers(void)
01046 {
01047 enum Token the_reg;
01048 uint16 value16;
01049 uint8 value;
01050
01051 if (the_token != T_END)
01052 switch (the_reg = the_token) {
01053 case T_A:
01054 case T_X:
01055 case T_Y:
01056 case T_PC:
01057 case T_SP:
01058 case T_DR:
01059 case T_PR:
01060 get_token();
01061 if (!expression(&value16))
01062 return;
01063
01064 value = (uint8)value16;
01065 switch (the_reg) {
01066 case T_A:
01067 if (access_1541)
01068 R1541.a = value;
01069 else
01070 R64.a = value;
01071 break;
01072 case T_X:
01073 if (access_1541)
01074 R1541.x = value;
01075 else
01076 R64.x = value;
01077 break;
01078 case T_Y:
01079 if (access_1541)
01080 R1541.y = value;
01081 else
01082 R64.y = value;
01083 break;
01084 case T_PC:
01085 if (access_1541)
01086 R1541.pc = value;
01087 else
01088 R64.pc = value;
01089 break;
01090 case T_SP:
01091 if (access_1541)
01092 R1541.sp = (value & 0xff) | 0x0100;
01093 else
01094 R64.sp = (value & 0xff) | 0x0100;
01095 break;
01096 case T_DR:
01097 if (!access_1541)
01098 R64.ddr = value;
01099 break;
01100 case T_PR:
01101 if (!access_1541)
01102 R64.pr = value;
01103 break;
01104 default:
01105 break;
01106 }
01107 break;
01108
01109 default:
01110 return;
01111 }
01112
01113 display_registers();
01114 }
01115
01116 static void display_registers(void)
01117 {
01118 if (access_1541) {
01119 fprintf(fout, " PC A X Y SP NVDIZC Instruction\n");
01120
01121
01122
01123
01124
01125
01126
01127
01128 fprintf(fout, "%04x %02x %02x %02x %04x %c%c%c%c%c%c ",
01129 R1541.pc,
01130 R1541.a,
01131 R1541.x,
01132 R1541.y,
01133 R1541.sp,
01134 R1541.p & 0x80 ? '1' : '0',
01135 R1541.p & 0x40 ? '1' : '0',
01136 R1541.p & 0x08 ? '1' : '0',
01137 R1541.p & 0x04 ? '1' : '0',
01138 R1541.p & 0x02 ? '1' : '0',
01139 R1541.p & 0x01 ? '1' : '0');
01140
01141 disass_line(R1541.pc, SAMReadByte(R1541.pc), SAMReadByte(R1541.pc+1), SAMReadByte(R1541.pc+2));
01142 } else {
01143 fprintf(fout, " PC A X Y SP DR PR NVDIZC Instruction\n");
01144
01145
01146
01147
01148
01149
01150
01151 fprintf(fout, "%04x %02x %02x %02x %04x %02x %02x %c%c%c%c%c%c ",
01152 R64.pc,
01153 R64.a,
01154 R64.x,
01155 R64.y,
01156 R64.sp,
01157 R64.ddr,
01158 R64.pr,
01159 R64.p & 0x80 ? '1' : '0',
01160 R64.p & 0x40 ? '1' : '0',
01161 R64.p & 0x08 ? '1' : '0',
01162 R64.p & 0x04 ? '1' : '0',
01163 R64.p & 0x02 ? '1' : '0',
01164 R64.p & 0x01 ? '1' : '0');
01165
01166 disass_line(R64.pc, SAMReadByte(R64.pc), SAMReadByte(R64.pc+1), SAMReadByte(R64.pc+2));
01167 }
01168 }
01169
01170
01171
01172
01173
01174
01175
01176 #define MEMDUMP_BPL 16 // Bytes per line
01177
01178 static void memory_dump(void)
01179 {
01180 bool done = false;
01181 short i;
01182 uint8 mem[MEMDUMP_BPL + 2];
01183 uint8 byte;
01184
01185 mem[MEMDUMP_BPL] = 0;
01186
01187 if (!range_args(16 * MEMDUMP_BPL - 1))
01188 return;
01189
01190 do {
01191
01192 fprintf(fout, "%04x:", address);
01193 for (i=0; i<MEMDUMP_BPL; i++, address++) {
01194 if (address == end_address) done = true;
01195
01196
01197 fprintf(fout, " %02x", byte = SAMReadByte(address));
01198 if ((byte >= ' ') && (byte <= '~'))
01199 mem[i] = conv_from_64(byte);
01200 else
01201 mem[i] = '.';
01202 }
01203 fprintf(fout, " '%s'\n", mem);
01204 } while (!done && !aborted());
01205 }
01206
01207
01208
01209
01210
01211
01212
01213 #define ASCIIDUMP_BPL 64 // Bytes per line
01214
01215 static void ascii_dump(void)
01216 {
01217 bool done = false;
01218 short i;
01219 uint8 mem[ASCIIDUMP_BPL + 2];
01220 uint8 byte;
01221
01222 mem[ASCIIDUMP_BPL] = 0;
01223
01224 if (!range_args(16 * ASCIIDUMP_BPL - 1))
01225 return;
01226
01227 do {
01228
01229 fprintf(fout, "%04x:", address);
01230 for (i=0; i<ASCIIDUMP_BPL; i++, address++) {
01231 if (address == end_address) done = true;
01232
01233 byte = SAMReadByte(address);
01234 if ((byte >= ' ') && (byte <= '~'))
01235 mem[i] = conv_from_64(byte);
01236 else
01237 mem[i] = '.';
01238 }
01239 fprintf(fout, " '%s'\n", mem);
01240 } while (!done && !aborted());
01241 }
01242
01243
01244
01245
01246
01247
01248 static char conv_from_64(char c)
01249 {
01250 if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
01251 return c ^ 0x20;
01252 else
01253 return c;
01254 }
01255
01256
01257
01258
01259
01260
01261
01262 #define SCRDUMP_BPL 64 // Bytes per line
01263
01264 static void screen_dump(void)
01265 {
01266 bool done = false;
01267 short i;
01268 uint8 mem[SCRDUMP_BPL + 2];
01269 uint8 byte;
01270
01271 mem[SCRDUMP_BPL] = 0;
01272
01273 if (!range_args(16 * SCRDUMP_BPL - 1))
01274 return;
01275
01276 do {
01277
01278 fprintf(fout, "%04x:", address);
01279 for (i=0; i<SCRDUMP_BPL; i++, address++) {
01280 if (address == end_address) done = true;
01281
01282 byte = SAMReadByte(address);
01283 if (byte < 90)
01284 mem[i] = conv_from_scode(byte);
01285 else
01286 mem[i] = '.';
01287 }
01288 fprintf(fout, " '%s'\n", mem);
01289 } while (!done && !aborted());
01290 }
01291
01292
01293
01294
01295
01296
01297 static char conv_from_scode(char c)
01298 {
01299 c &= 0x7f;
01300
01301 if (c <= 31)
01302 return c + 64;
01303 else
01304 if (c >= 64)
01305 return c + 32;
01306 else
01307 return c;
01308 }
01309
01310
01311
01312
01313
01314
01315
01316 static void binary_dump(void)
01317 {
01318 bool done = false;
01319 char bin[10];
01320
01321 bin[8] = 0;
01322
01323 if (!range_args(7))
01324 return;
01325
01326 do {
01327 if (address == end_address) done = true;
01328
01329 byte_to_bin(SAMReadByte(address), bin);
01330
01331 fprintf(fout, "%04x: %s\n", address++, bin);
01332 } while (!done && !aborted());
01333 }
01334
01335
01336
01337
01338
01339
01340
01341 static void sprite_dump(void)
01342 {
01343 bool done = false;
01344 short i;
01345 char bin[10];
01346
01347 bin[8] = 0;
01348
01349 if (!range_args(21 * 3 - 1))
01350 return;
01351
01352 do {
01353
01354 fprintf(fout, "%04x: ", address);
01355 for (i=0; i<3; i++, address++) {
01356 if (address == end_address) done = true;
01357
01358 byte_to_bin(SAMReadByte(address), bin);
01359 fprintf(fout, "%s", bin);
01360 }
01361 fputc('\n', fout);
01362 } while (!done && !aborted());
01363 }
01364
01365
01366
01367
01368
01369
01370 static void byte_to_bin(uint8 byte, char *str)
01371 {
01372 short i;
01373
01374 for (i=0; i<8; i++, byte<<=1)
01375 if (byte & 0x80)
01376 str[i] = '#';
01377 else
01378 str[i] = '.';
01379 }
01380
01381
01382
01383
01384
01385
01386
01387 static void disassemble(void)
01388 {
01389 bool done = false;
01390 short i;
01391 uint8 op[3];
01392 uint16 adr;
01393
01394 if (!range_args(31))
01395 return;
01396
01397 do {
01398
01399 fprintf(fout, "%04x:", adr = address);
01400 for (i=0; i<3; i++, adr++) {
01401 if (adr == end_address) done = true;
01402 op[i] = SAMReadByte(adr);
01403 }
01404 address += disass_line(address, op[0], op[1], op[2]);
01405 } while (!done && !aborted());
01406 }
01407
01408
01409
01410
01411
01412
01413 static int disass_line(uint16 adr, uint8 op, uint8 lo, uint8 hi)
01414 {
01415 char mode = adr_mode[op], mnem = mnemonic[op];
01416
01417
01418 switch (adr_length[mode]) {
01419 case 1:
01420
01421 fprintf(fout, " %02x ", op);
01422 break;
01423
01424 case 2:
01425
01426 fprintf(fout, " %02x %02x ", op, lo);
01427 break;
01428
01429 case 3:
01430
01431 fprintf(fout, " %02x %02x %02x ", op, lo, hi);
01432 break;
01433 }
01434
01435
01436 if (mnem > M_ILLEGAL)
01437 fputc('*', fout);
01438 else
01439 fputc(' ', fout);
01440
01441
01442 fprintf(fout, "%c%c%c ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem]);
01443
01444
01445 switch (mode) {
01446 case A_IMPL:
01447 break;
01448
01449 case A_ACCU:
01450 fprintf(fout, "a");
01451 break;
01452
01453 case A_IMM:
01454
01455 fprintf(fout, "#%02x", lo);
01456 break;
01457
01458 case A_REL:
01459
01460 fprintf(fout, "%04x", ((adr + 2) + (int8)lo) & 0xffff);
01461 break;
01462
01463 case A_ZERO:
01464
01465 fprintf(fout, "%02x", lo);
01466 break;
01467
01468 case A_ZEROX:
01469
01470 fprintf(fout, "%02x,x", lo);
01471 break;
01472
01473 case A_ZEROY:
01474
01475 fprintf(fout, "%02x,y", lo);
01476 break;
01477
01478 case A_ABS:
01479
01480 fprintf(fout, "%04x", (hi << 8) | lo);
01481 break;
01482
01483 case A_ABSX:
01484
01485 fprintf(fout, "%04x,x", (hi << 8) | lo);
01486 break;
01487
01488 case A_ABSY:
01489
01490 fprintf(fout, "%04x,y", (hi << 8) | lo);
01491 break;
01492
01493 case A_IND:
01494
01495 fprintf(fout, "(%04x)", (hi << 8) | lo);
01496 break;
01497
01498 case A_INDX:
01499
01500 fprintf(fout, "(%02x,x)", lo);
01501 break;
01502
01503 case A_INDY:
01504
01505 fprintf(fout, "(%02x),y", lo);
01506 break;
01507 }
01508
01509 fputc('\n', fout);
01510 return adr_length[mode];
01511 }
01512
01513
01514
01515
01516
01517
01518
01519 static void assemble(void)
01520 {
01521 bool done = false;
01522 char c1, c2, c3;
01523 char mnem, mode;
01524 uint8 opcode;
01525 uint16 arg;
01526 int16 rel;
01527
01528
01529 if (!address_args())
01530 return;
01531
01532 do {
01533
01534 fprintf(fout, "%04x> ", address);
01535 fflush(ferr);
01536 read_line();
01537
01538 c1 = get_char();
01539 c2 = get_char();
01540 c3 = get_char();
01541
01542 if (c1 != '\n') {
01543
01544 if ((mnem = find_mnemonic(c1, c2, c3)) != M_ILLEGAL) {
01545
01546 get_token();
01547 if (instr_args(&arg, &mode)) {
01548
01549
01550 if ((mode == A_IMPL) && find_opcode(mnem, A_ACCU, &opcode))
01551 mode = A_ACCU;
01552
01553
01554 if (((mode == A_ABS) || (mode == A_ZERO)) && find_opcode(mnem, A_REL, &opcode)) {
01555 mode = A_REL;
01556 rel = arg - (address + 2) & 0xffff;
01557 if ((rel < -128) || (rel > 127)) {
01558 error("Branch too long");
01559 continue;
01560 } else
01561 arg = rel & 0xff;
01562 }
01563
01564 if (find_opcode(mnem, mode, &opcode)) {
01565
01566
01567
01568 fprintf(fout, "\v%04x:", address);
01569 disass_line(address, opcode, arg & 0xff, arg >> 8);
01570
01571 switch (adr_length[mode]) {
01572 case 1:
01573 SAMWriteByte(address++, opcode);
01574 break;
01575
01576 case 2:
01577 SAMWriteByte(address++, opcode);
01578
01579 SAMWriteByte(address++, (uint8)arg);
01580 break;
01581
01582 case 3:
01583 SAMWriteByte(address++, opcode);
01584 SAMWriteByte(address++, arg & 0xff);
01585 SAMWriteByte(address++, arg >> 8);
01586 break;
01587
01588 default:
01589 error("Internal error");
01590 break;
01591 }
01592
01593 } else
01594 error("Addressing mode not supported by instruction");
01595
01596 } else
01597 error("Unrecognized addressing mode");
01598
01599 } else
01600 error("Unknown instruction");
01601
01602 } else
01603 done = true;
01604 } while (!done);
01605 }
01606
01607
01608
01609
01610
01611
01612
01613 static char find_mnemonic(char op1, char op2, char op3)
01614 {
01615 int i;
01616
01617 for (i=0; i<M_MAXIMUM; i++)
01618 if ((mnem_1[i] == op1) && (mnem_2[i] == op2) && (mnem_3[i] == op3))
01619 return i;
01620
01621 return M_ILLEGAL;
01622 }
01623
01624
01625
01626
01627
01628
01629
01630 static bool find_opcode(char mnem, char mode, uint8 *opcode)
01631 {
01632 int i;
01633
01634 for (i=0; i<256; i++)
01635 if ((mnemonic[i] == mnem) && (adr_mode[i] == mode)) {
01636 *opcode = i;
01637 return true;
01638 }
01639
01640 return false;
01641 }
01642
01643
01644
01645
01646
01647
01648
01649 static void mem_config(void)
01650 {
01651 uint16 con;
01652
01653 if (the_token != T_END)
01654 if (!expression(&con))
01655 return;
01656 else
01657 TheCPU->ExtConfig = con;
01658 else
01659 con = TheCPU->ExtConfig;
01660
01661
01662 fprintf(fout, "Configuration: %d\n", con & 7);
01663 fprintf(fout, "A000-BFFF: %s\n", (con & 3) == 3 ? "Basic" : "RAM");
01664 fprintf(fout, "D000-DFFF: %s\n", (con & 3) ? ((con & 4) ? "I/O" : "Char") : "RAM");
01665 fprintf(fout, "E000-FFFF: %s\n", (con & 2) ? "Kernal" : "RAM");
01666 }
01667
01668
01669
01670
01671
01672
01673
01674 static void fill(void)
01675 {
01676 bool done = false;
01677 uint16 adr, end_adr, value;
01678
01679 if (!expression(&adr))
01680 return;
01681 if (!expression(&end_adr))
01682 return;
01683 if (!expression(&value))
01684 return;
01685
01686 do {
01687 if (adr == end_adr) done = true;
01688
01689
01690 SAMWriteByte(adr++, (uint8)value);
01691 } while (!done);
01692 }
01693
01694
01695
01696
01697
01698
01699
01700 static void compare(void)
01701 {
01702 bool done = false;
01703 uint16 adr, end_adr, dest;
01704 int num = 0;
01705
01706 if (!expression(&adr))
01707 return;
01708 if (!expression(&end_adr))
01709 return;
01710 if (!expression(&dest))
01711 return;
01712
01713 do {
01714 if (adr == end_adr) done = true;
01715
01716 if (SAMReadByte(adr) != SAMReadByte(dest)) {
01717
01718 fprintf(fout, "%04x ", adr);
01719 num++;
01720 if (!(num & 7))
01721 fputc('\n', fout);
01722 }
01723 adr++; dest++;
01724 } while (!done && !aborted());
01725
01726 if (num & 7)
01727 fputc('\n', fout);
01728
01729 fprintf(fout, "%d byte(s) different\n", num);
01730 }
01731
01732
01733
01734
01735
01736
01737
01738 static void transfer(void)
01739 {
01740 bool done = false;
01741 uint16 adr, end_adr, dest;
01742
01743 if (!expression(&adr))
01744 return;
01745 if (!expression(&end_adr))
01746 return;
01747 if (!expression(&dest))
01748 return;
01749
01750 if (dest < adr)
01751 do {
01752 if (adr == end_adr) done = true;
01753 SAMWriteByte(dest++, SAMReadByte(adr++));
01754 } while (!done);
01755 else {
01756 dest += end_adr - adr;
01757 do {
01758 if (adr == end_adr) done = true;
01759 SAMWriteByte(dest--, SAMReadByte(end_adr--));
01760 } while (!done);
01761 }
01762 }
01763
01764
01765
01766
01767
01768
01769
01770 static void modify(void)
01771 {
01772 uint16 adr, val;
01773
01774 if (!expression(&adr))
01775 return;
01776
01777 while (the_token != T_END)
01778 if (expression(&val))
01779
01780 SAMWriteByte(adr++, (uint8)val);
01781 else
01782 return;
01783 }
01784
01785
01786
01787
01788
01789
01790
01791 static void print_expr(void)
01792 {
01793 uint16 val;
01794
01795 if (!expression(&val))
01796 return;
01797
01798
01799 fprintf(fout, "Hex: %04x\nDec: %u\n", val, val);
01800 }
01801
01802
01803
01804
01805
01806
01807
01808 static void redir_output(void)
01809 {
01810
01811 if (the_token == T_END)
01812 return;
01813
01814
01815 if (the_token == T_STRING) {
01816 if (!(fout = fopen(the_string, "w")))
01817 error("Unable to open file");
01818 } else
01819 error("'\"' around file name expected");
01820 }
01821
01822
01823
01824
01825
01826
01827 static void int_vectors(void)
01828 {
01829 fprintf(fout, " IRQ BRK NMI\n");
01830
01831 fprintf(fout, "%d : %04x %04x %04x\n",
01832 access_1541 ? 6502 : 6510,
01833 SAMReadByte(0xffff) << 8 | SAMReadByte(0xfffe),
01834 SAMReadByte(0xffff) << 8 | SAMReadByte(0xfffe),
01835 SAMReadByte(0xfffb) << 8 | SAMReadByte(0xfffa));
01836
01837 if (!access_1541 && TheCPU->ExtConfig & 2)
01838
01839 fprintf(fout, "Kernal: %04x %04x %04x\n",
01840 SAMReadByte(0x0315) << 8 | SAMReadByte(0x0314),
01841 SAMReadByte(0x0317) << 8 | SAMReadByte(0x0316),
01842 SAMReadByte(0x0319) << 8 | SAMReadByte(0x0318));
01843 }
01844
01845
01846
01847
01848
01849
01850 static void view_state(void)
01851 {
01852 switch (get_char()) {
01853 case 'c':
01854 view_cia_state();
01855 break;
01856
01857 case 's':
01858 view_sid_state();
01859 break;
01860
01861 case 'v':
01862 view_vic_state();
01863 break;
01864
01865 case 'f':
01866 view_1541_state();
01867 break;
01868
01869 default:
01870 error("Unknown command");
01871 break;
01872 }
01873 }
01874
01875 static void view_cia_state(void)
01876 {
01877 MOS6526State cs;
01878
01879 switch (get_char()) {
01880 case '1':
01881 TheCIA1->GetState(&cs);
01882 break;
01883 case '2':
01884 TheCIA2->GetState(&cs);
01885 break;
01886 default:
01887 error("Unknown command");
01888 return;
01889 }
01890
01891 fprintf(fout, "Timer A : %s\n", cs.cra & 1 ? "On" : "Off");
01892
01893 fprintf(fout, " Counter : %04x Latch: %04x\n", (cs.ta_hi << 8) | cs.ta_lo, cs.latcha);
01894 fprintf(fout, " Run mode: %s\n", cs.cra & 8 ? "One-shot" : "Continuous");
01895 fprintf(fout, " Input : %s\n", cs.cra & 0x20 ? "CNT" : "Phi2");
01896 fprintf(fout, " Output : ");
01897 if (cs.cra & 2)
01898 if (cs.cra & 4)
01899 fprintf(fout, "PB6 Toggle\n\n");
01900 else
01901 fprintf(fout, "PB6 Pulse\n\n");
01902 else
01903 fprintf(fout, "None\n\n");
01904
01905 fprintf(fout, "Timer B : %s\n", cs.crb & 1 ? "On" : "Off");
01906
01907 fprintf(fout, " Counter : %04x Latch: %04x\n", (cs.tb_hi << 8) | cs.tb_lo, cs.latchb);
01908 fprintf(fout, " Run mode: %s\n", cs.crb & 8 ? "One-shot" : "Continuous");
01909 fprintf(fout, " Input : ");
01910 if (cs.crb & 0x40)
01911 if (cs.crb & 0x20)
01912 fprintf(fout, "Timer A underflow (CNT high)\n");
01913 else
01914 fprintf(fout, "Timer A underflow\n");
01915 else
01916 if (cs.crb & 0x20)
01917 fprintf(fout, "CNT\n");
01918 else
01919 fprintf(fout, "Phi2\n");
01920 fprintf(fout, " Output : ");
01921 if (cs.crb & 2)
01922 if (cs.crb & 4)
01923 fprintf(fout, "PB7 Toggle\n\n");
01924 else
01925 fprintf(fout, "PB7 Pulse\n\n");
01926 else
01927 fprintf(fout, "None\n\n");
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941 fprintf(fout, "TOD : %x%x:%x%x:%x%x.%x %s\n",
01942 (cs.tod_hr >> 4) & 1, cs.tod_hr & 0x0f,
01943 (cs.tod_min >> 4) & 7, cs.tod_min & 0x0f,
01944 (cs.tod_sec >> 4) & 7, cs.tod_sec & 0x0f,
01945 cs.tod_10ths & 0x0f, cs.tod_hr & 0x80 ? "PM" : "AM");
01946 fprintf(fout, "Alarm : %x%x:%x%x:%x%x.%x %s\n",
01947 (cs.alm_hr >> 4) & 1, cs.alm_hr & 0x0f,
01948 (cs.alm_min >> 4) & 7, cs.alm_min & 0x0f,
01949 (cs.alm_sec >> 4) & 7, cs.alm_sec & 0x0f,
01950 cs.alm_10ths & 0x0f, cs.alm_hr & 0x80 ? "PM" : "AM");
01951
01952
01953
01954 fprintf(fout, "TOD input : %s\n", cs.cra & 0x80 ? "50Hz" : "60Hz");
01955 fprintf(fout, "Write to : %s registers\n\n", cs.crb & 0x80 ? "Alarm" : "TOD");
01956
01957
01958 fprintf(fout, "Serial data : %02x\n", cs.sdr);
01959 fprintf(fout, "Serial mode : %s\n\n", cs.cra & 0x40 ? "Output" : "Input");
01960
01961 fprintf(fout, "Pending int.: ");
01962 dump_cia_ints(cs.int_data);
01963 fprintf(fout, "Enabled int.: ");
01964 dump_cia_ints(cs.int_mask);
01965 }
01966
01967 static void dump_cia_ints(uint8 i)
01968 {
01969 if (i & 0x1f) {
01970 if (i & 1) fprintf(fout, "TA ");
01971 if (i & 2) fprintf(fout, "TB ");
01972 if (i & 4) fprintf(fout, "Alarm ");
01973 if (i & 8) fprintf(fout, "Serial ");
01974 if (i & 0x10) fprintf(fout, "Flag");
01975 } else
01976 fprintf(fout, "None");
01977 fputc('\n', fout);
01978 }
01979
01980 static void view_sid_state(void)
01981 {
01982 MOS6581State ss;
01983
01984 TheSID->GetState(&ss);
01985
01986 fprintf(fout, "Voice 1\n");
01987
01988 fprintf(fout, " Frequency : %04x\n", (ss.freq_hi_1 << 8) | ss.freq_lo_1);
01989
01990 fprintf(fout, " Pulse Width: %04x\n", ((ss.pw_hi_1 & 0x0f) << 8) | ss.pw_lo_1);
01991
01992 fprintf(fout, " Env. (ADSR): %x %x %x %x\n", ss.AD_1 >> 4, ss.AD_1 & 0x0f, ss.SR_1 >> 4, ss.SR_1 & 0x0f);
01993 fprintf(fout, " Waveform : ");
01994 dump_sid_waveform(ss.ctrl_1);
01995 fprintf(fout, " Gate : %s Ring mod.: %s\n", ss.ctrl_1 & 0x01 ? "On " : "Off", ss.ctrl_1 & 0x04 ? "On" : "Off");
01996 fprintf(fout, " Test bit : %s Synchron.: %s\n", ss.ctrl_1 & 0x08 ? "On " : "Off", ss.ctrl_1 & 0x02 ? "On" : "Off");
01997 fprintf(fout, " Filter : %s\n", ss.res_filt & 0x01 ? "On" : "Off");
01998
01999 fprintf(fout, "\nVoice 2\n");
02000
02001
02002 fprintf(fout, " Frequency : %04x\n", (ss.freq_hi_2 << 8) | ss.freq_lo_2);
02003 fprintf(fout, " Pulse Width: %04x\n", ((ss.pw_hi_2 & 0x0f) << 8) | ss.pw_lo_2);
02004
02005 fprintf(fout, " Env. (ADSR): %x %x %x %x\n", ss.AD_2 >> 4, ss.AD_2 & 0x0f, ss.SR_2 >> 4, ss.SR_2 & 0x0f);
02006 fprintf(fout, " Waveform : ");
02007 dump_sid_waveform(ss.ctrl_2);
02008 fprintf(fout, " Gate : %s Ring mod.: %s\n", ss.ctrl_2 & 0x01 ? "On " : "Off", ss.ctrl_2 & 0x04 ? "On" : "Off");
02009 fprintf(fout, " Test bit : %s Synchron.: %s\n", ss.ctrl_2 & 0x08 ? "On " : "Off", ss.ctrl_2 & 0x02 ? "On" : "Off");
02010 fprintf(fout, " Filter : %s\n", ss.res_filt & 0x02 ? "On" : "Off");
02011
02012 fprintf(fout, "\nVoice 3\n");
02013
02014
02015 fprintf(fout, " Frequency : %04x\n", (ss.freq_hi_3 << 8) | ss.freq_lo_3);
02016 fprintf(fout, " Pulse Width: %04x\n", ((ss.pw_hi_3 & 0x0f) << 8) | ss.pw_lo_3);
02017
02018 fprintf(fout, " Env. (ADSR): %x %x %x %x\n", ss.AD_3 >> 4, ss.AD_3 & 0x0f, ss.SR_3 >> 4, ss.SR_3 & 0x0f);
02019 fprintf(fout, " Waveform : ");
02020 dump_sid_waveform(ss.ctrl_3);
02021 fprintf(fout, " Gate : %s Ring mod.: %s\n", ss.ctrl_3 & 0x01 ? "On " : "Off", ss.ctrl_3 & 0x04 ? "On" : "Off");
02022 fprintf(fout, " Test bit : %s Synchron.: %s\n", ss.ctrl_3 & 0x08 ? "On " : "Off", ss.ctrl_3 & 0x02 ? "On" : "Off");
02023 fprintf(fout, " Filter : %s Mute : %s\n", ss.res_filt & 0x04 ? "On" : "Off", ss.mode_vol & 0x80 ? "Yes" : "No");
02024
02025 fprintf(fout, "\nFilters/Volume\n");
02026
02027 fprintf(fout, " Frequency: %04x\n", (ss.fc_hi << 3) | (ss.fc_lo & 0x07));
02028
02029 fprintf(fout, " Resonance: %x\n", ss.res_filt >> 4);
02030 fprintf(fout, " Mode : ");
02031 if (ss.mode_vol & 0x70) {
02032 if (ss.mode_vol & 0x10) fprintf(fout, "Low-pass ");
02033 if (ss.mode_vol & 0x20) fprintf(fout, "Band-pass ");
02034 if (ss.mode_vol & 0x40) fprintf(fout, "High-pass");
02035 } else
02036 fprintf(fout, "None");
02037
02038 fprintf(fout, "\n Volume : %x\n", ss.mode_vol & 0x0f);
02039 }
02040
02041 static void dump_sid_waveform(uint8 wave)
02042 {
02043 if (wave & 0xf0) {
02044 if (wave & 0x10) fprintf(fout, "Triangle ");
02045 if (wave & 0x20) fprintf(fout, "Sawtooth ");
02046 if (wave & 0x40) fprintf(fout, "Rectangle ");
02047 if (wave & 0x80) fprintf(fout, "Noise");
02048 } else
02049 fprintf(fout, "None");
02050 fputc('\n', fout);
02051 }
02052
02053 static void view_vic_state(void)
02054 {
02055 MOS6569State vs;
02056 short i;
02057
02058 TheVIC->GetState(&vs);
02059
02060
02061
02062
02063 fprintf(fout, "Raster line : %04x\n", vs.raster | ((vs.ctrl1 & 0x80) << 1));
02064 fprintf(fout, "IRQ raster line : %04x\n\n", vs.irq_raster);
02065
02066
02067
02068
02069
02070
02071
02072 fprintf(fout, "X scroll : %d\n", vs.ctrl2 & 7);
02073 fprintf(fout, "Y scroll : %d\n", vs.ctrl1 & 7);
02074 fprintf(fout, "Horizontal border : %d columns\n", vs.ctrl2 & 8 ? 40 : 38);
02075 fprintf(fout, "Vertical border : %d rows\n\n", vs.ctrl1 & 8 ? 25 : 24);
02076
02077
02078 fprintf(fout, "Display mode : ");
02079 switch (((vs.ctrl1 >> 4) & 6) | ((vs.ctrl2 >> 4) & 1)) {
02080 case 0:
02081 fprintf(fout, "Standard text\n");
02082 break;
02083 case 1:
02084 fprintf(fout, "Multicolor text\n");
02085 break;
02086 case 2:
02087 fprintf(fout, "Standard bitmap\n");
02088 break;
02089 case 3:
02090 fprintf(fout, "Multicolor bitmap\n");
02091 break;
02092 case 4:
02093 fprintf(fout, "ECM text\n");
02094 break;
02095 case 5:
02096 fprintf(fout, "Invalid text (ECM+MCM)\n");
02097 break;
02098 case 6:
02099 fprintf(fout, "Invalid bitmap (ECM+BMM)\n");
02100 break;
02101 case 7:
02102 fprintf(fout, "Invalid bitmap (ECM+BMM+ECM)\n");
02103 break;
02104 }
02105 fprintf(fout, "Sequencer state : %s\n", vs.display_state ? "Display" : "Idle");
02106 fprintf(fout, "Bad line state : %s\n", vs.bad_line ? "Yes" : "No");
02107 fprintf(fout, "Bad lines enabled : %s\n", vs.bad_line_enable ? "Yes" : "No");
02108
02109
02110 fprintf(fout, "Video counter : %04x\n", vs.vc);
02111 fprintf(fout, "Video counter base: %04x\n", vs.vc_base);
02112
02113 fprintf(fout, "Row counter : %d\n\n", vs.rc);
02114
02115
02116
02117
02118
02119
02120
02121 fprintf(fout, "VIC bank : %04x-%04x\n", vs.bank_base, vs.bank_base + 0x3fff);
02122 fprintf(fout, "Video matrix base : %04x\n", vs.matrix_base);
02123 fprintf(fout, "Character base : %04x\n", vs.char_base);
02124 fprintf(fout, "Bitmap base : %04x\n\n", vs.bitmap_base);
02125
02126
02127 fprintf(fout, " Spr.0 Spr.1 Spr.2 Spr.3 Spr.4 Spr.5 Spr.6 Spr.7\n");
02128 fprintf(fout, "Enabled: "); dump_spr_flags(vs.me);
02129
02130 fprintf(fout, "Data : %04x %04x %04x %04x %04x %04x %04x %04x\n",
02131 vs.sprite_base[0], vs.sprite_base[1], vs.sprite_base[2], vs.sprite_base[3],
02132 vs.sprite_base[4], vs.sprite_base[5], vs.sprite_base[6], vs.sprite_base[7]);
02133
02134 fprintf(fout, "MC : %02x %02x %02x %02x %02x %02x %02x %02x\n",
02135 vs.mc[0], vs.mc[1], vs.mc[2], vs.mc[3], vs.mc[4], vs.mc[5], vs.mc[6], vs.mc[7]);
02136
02137 fprintf(fout, "Mode : ");
02138 for (i=0; i<8; i++)
02139 if (vs.mmc & (1<<i))
02140 fprintf(fout, "Multi ");
02141 else
02142 fprintf(fout, "Std. ");
02143
02144 fprintf(fout, "\nX-Exp. : "); dump_spr_flags(vs.mxe);
02145 fprintf(fout, "Y-Exp. : "); dump_spr_flags(vs.mye);
02146
02147 fprintf(fout, "Prio. : ");
02148 for (i=0; i<8; i++)
02149 if (vs.mdp & (1<<i))
02150 fprintf(fout, "Back ");
02151 else
02152 fprintf(fout, "Fore ");
02153
02154 fprintf(fout, "\n\nPending interrupts: ");
02155 dump_vic_ints(vs.irq_flag);
02156 fprintf(fout, "Enabled interrupts: ");
02157 dump_vic_ints(vs.irq_mask);
02158 }
02159
02160 static void dump_spr_flags(uint8 f)
02161 {
02162 short i;
02163
02164 for (i=0; i<8; i++)
02165 if (f & (1<<i))
02166 fprintf(fout, "Yes ");
02167 else
02168 fprintf(fout, "No ");
02169
02170 fputc('\n', fout);
02171 }
02172
02173 static void dump_vic_ints(uint8 i)
02174 {
02175 if (i & 0x1f) {
02176 if (i & 1) fprintf(fout, "Raster ");
02177 if (i & 2) fprintf(fout, "Spr-Data ");
02178 if (i & 4) fprintf(fout, "Spr-Spr ");
02179 if (i & 8) fprintf(fout, "Lightpen");
02180 } else
02181 fprintf(fout, "None");
02182 fputc('\n', fout);
02183 }
02184
02185 static void view_1541_state(void)
02186 {
02187 fprintf(fout, "VIA 1:\n");
02188 fprintf(fout, " Timer 1 Counter: %04x Latch: %04x\n", R1541.via1_t1c, R1541.via1_t1l);
02189 fprintf(fout, " Timer 2 Counter: %04x Latch: %04x\n", R1541.via1_t2c, R1541.via1_t2l);
02190 fprintf(fout, " ACR: %02x\n", R1541.via1_acr);
02191 fprintf(fout, " PCR: %02x\n", R1541.via1_pcr);
02192 fprintf(fout, " Pending interrupts: ");
02193 dump_via_ints(R1541.via1_ifr);
02194 fprintf(fout, " Enabled interrupts: ");
02195 dump_via_ints(R1541.via1_ier);
02196
02197 fprintf(fout, "\nVIA 2:\n");
02198 fprintf(fout, " Timer 1 Counter: %04x Latch: %04x\n", R1541.via2_t1c, R1541.via2_t1l);
02199 fprintf(fout, " Timer 2 Counter: %04x Latch: %04x\n", R1541.via2_t2c, R1541.via2_t2l);
02200 fprintf(fout, " ACR: %02x\n", R1541.via2_acr);
02201 fprintf(fout, " PCR: %02x\n", R1541.via2_pcr);
02202 fprintf(fout, " Pending interrupts: ");
02203 dump_via_ints(R1541.via2_ifr);
02204 fprintf(fout, " Enabled interrupts: ");
02205 dump_via_ints(R1541.via2_ier);
02206 }
02207
02208 static void dump_via_ints(uint8 i)
02209 {
02210 if (i & 0x7f) {
02211 if (i & 0x40) fprintf(fout, "T1 ");
02212 if (i & 0x20) fprintf(fout, "T2 ");
02213 if (i & 2) fprintf(fout, "CA1 ");
02214 if (i & 1) fprintf(fout, "CA2 ");
02215 if (i & 0x10) fprintf(fout, "CB1 ");
02216 if (i & 8) fprintf(fout, "CB2 ");
02217 if (i & 4) fprintf(fout, "Serial ");
02218 } else
02219 fprintf(fout, "None");
02220 fputc('\n', fout);
02221 }
02222
02223
02224
02225
02226
02227
02228
02229 static void load_data(void)
02230 {
02231 uint16 adr;
02232 FILE *file;
02233 int fc;
02234
02235 if (!expression(&adr))
02236 return;
02237 if (the_token == T_END) {
02238 error("Missing file name");
02239 return;
02240 }
02241 if (the_token != T_STRING) {
02242 error("'\"' around file name expected");
02243 return;
02244 }
02245
02246 if (!(file = fopen(the_string, "rb")))
02247 error("Unable to open file");
02248 else {
02249 while ((fc = fgetc(file)) != EOF)
02250 SAMWriteByte(adr++, fc);
02251 fclose(file);
02252 }
02253 }
02254
02255
02256
02257
02258
02259
02260
02261 static void save_data(void)
02262 {
02263 bool done = false;
02264 uint16 adr, end_adr;
02265 FILE *file;
02266
02267 if (!expression(&adr))
02268 return;
02269 if (!expression(&end_adr))
02270 return;
02271 if (the_token == T_END) {
02272 error("Missing file name");
02273 return;
02274 }
02275 if (the_token != T_STRING) {
02276 error("'\"' around file name expected");
02277 return;
02278 }
02279
02280 if (!(file = fopen(the_string, "wb")))
02281 error("Unable to create file");
02282 else {
02283 do {
02284 if (adr == end_adr) done = true;
02285
02286 fputc(SAMReadByte(adr++), file);
02287 } while (!done);
02288 fclose(file);
02289 }
02290 }