Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

SAM.cpp

Go to the documentation of this file.
00001 /*
00002  *  SAM.h - Simple Assembler and Monitor With Integrated System Explorer
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
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 // Pointers to chips
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 // 6510/6502 registers
00027 static MOS6510State R64;
00028 static MOS6502State R1541;
00029 
00030 static bool access_1541;        // false: accessing C64, true: accessing 1541
00031 
00032 // Access to 6510/6502 address space
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 // Streams for input, output and error messages
00051 static FILE *fin, *fout, *ferr;
00052 
00053 // Input line
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 // Input tokens
00062 enum Token {
00063         T_NULL,         // Invalid token
00064         T_END,          // End of line
00065         T_NUMBER,       // Hexadecimal number
00066         T_STRING,       // String enclosed in ""
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,            // 'x'
00076         T_Y,            // 'y'
00077         T_PC,           // 'pc'
00078         T_SP,           // 'sp'
00079 
00080         T_A,            // 'a'  (get_reg_token() only)
00081         T_DR,           // 'dr' (get_reg_token() only)
00082         T_PR            // 'pr' (get_reg_token() only)
00083 };
00084 
00085 static enum Token the_token;                    // Last token read
00086 static uint16 the_number;                               // Contains the number if the_token==T_NUMBER
00087 static char the_string[INPUT_LENGTH];   // Contains the string if the_token==T_STRING
00088 
00089 
00090 // Addressing modes
00091 enum {
00092         A_IMPL,
00093         A_ACCU,         // A
00094         A_IMM,          // #zz
00095         A_REL,          // Branches
00096         A_ZERO,         // zz
00097         A_ZEROX,        // zz,x
00098         A_ZEROY,        // zz,y
00099         A_ABS,          // zzzz
00100         A_ABSX,         // zzzz,x
00101         A_ABSY,         // zzzz,y
00102         A_IND,          // (zzzz)
00103         A_INDX,         // (zz,x)
00104         A_INDY          // (zz),y
00105 };
00106 
00107 // Mnemonics
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,  // Undocumented opcodes start here
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  // Highest element
00123 };
00124 
00125 // Mnemonic for each opcode
00126 static const char mnemonic[256] = {
00127         M_BRK , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO,  // 00
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,  // 10
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,  // 20
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,  // 30
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,  // 40
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,  // 50
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,  // 60
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,  // 70
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,  // 80
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,  // 90
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,  // a0
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,  // b0
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,  // c0
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,  // d0
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,  // e0
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,  // f0
00158         M_SED , M_SBC , M_INOP, M_IISB, M_INOP, M_SBC, M_INC , M_IISB
00159 };
00160 
00161 // Addressing mode for each opcode
00162 static const char adr_mode[256] = {
00163         A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO,      // 00
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,     // 10
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,      // 20
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,     // 30
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,      // 40
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,     // 50
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,      // 60
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,     // 70
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,      // 80
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,     // 90
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,      // a0
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,     // b0
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,      // c0
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,     // d0
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,      // e0
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,     // f0
00194         A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX
00195 };
00196 
00197 // Chars for each mnemonic
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 // Instruction length for each addressing mode
00203 static const char adr_length[] = {1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2};
00204 
00205 
00206 // Prototypes
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);                    // Scanner
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); // Parser
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);                         // Routines for commands
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  *  Open and handle SAM
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         // Get CPU registers and current memory configuration
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':               // Assemble
00318                                 get_token();
00319                                 assemble();
00320                                 break;
00321 
00322                         case 'b':               // Binary dump
00323                                 get_token();
00324                                 binary_dump();
00325                                 break;
00326 
00327                         case 'c':               // Compare
00328                                 get_token();
00329                                 compare();
00330                                 break;
00331 
00332                         case 'd':               // Disassemble
00333                                 get_token();
00334                                 disassemble();
00335                                 break;
00336 
00337                         case 'e':       // Interrupt vectors
00338                                 int_vectors();
00339                                 break;
00340 
00341                         case 'f':               // Fill
00342                                 get_token();
00343                                 fill();
00344                                 break;
00345 
00346                         case 'h':               // Help
00347                                 help();
00348                                 break;
00349 
00350                         case 'i':               // ASCII dump
00351                                 get_token();
00352                                 ascii_dump();
00353                                 break;
00354 
00355                         case 'k':               // Memory configuration
00356                                 get_token();
00357                                 mem_config();
00358                                 break;
00359 
00360                         case 'l':               // Load data
00361                                 get_token();
00362                                 load_data();
00363                                 break;
00364 
00365                         case 'm':               // Memory dump
00366                                 get_token();
00367                                 memory_dump();
00368                                 break;
00369 
00370                         case 'n':               // Screen code dump
00371                                 get_token();
00372                                 screen_dump();
00373                                 break;
00374 
00375                         case 'o':               // Redirect output
00376                                 get_token();
00377                                 redir_output();
00378                                 break;
00379 
00380                         case 'p':               // Sprite dump
00381                                 get_token();
00382                                 sprite_dump();
00383                                 break;
00384 
00385                         case 'r':               // Registers
00386                                 get_reg_token();
00387                                 registers();
00388                                 break;
00389 
00390                         case 's':               // Save data
00391                                 get_token();
00392                                 save_data();
00393                                 break;
00394 
00395                         case 't':               // Transfer
00396                                 get_token();
00397                                 transfer();
00398                                 break;
00399 
00400                         case 'v':               // View machine state
00401                                 view_state();
00402                                 break;
00403 
00404                         case 'x':               // Exit
00405                                 done = true;
00406                                 break;
00407 
00408                         case ':':               // Change memory
00409                                 get_token();
00410                                 modify();
00411                                 break;
00412 
00413                         case '1':               // Switch to 1541 mode
00414                                 access_1541 = true;
00415                                 break;
00416 
00417                         case '6':               // Switch to C64 mode
00418                                 access_1541 = false;
00419                                 break;
00420 
00421                         case '?':               // Compute expression
00422                                 get_token();
00423                                 print_expr();
00424                                 break;
00425 
00426                         case '\n':              // Blank line
00427                                 break;
00428 
00429                         default:                // Unknown command
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         // Set CPU registers
00448         TheCPU->SetState(&R64);
00449         TheCPU1541->SetState(&R1541);
00450 }
00451 
00452 
00453 /*
00454  *  Print error message
00455  */
00456 
00457 static void error(char *s)
00458 {
00459         fprintf(ferr, "*** %s\n", s);
00460 }
00461 
00462 
00463 /*
00464  *  CTRL-C pressed?
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  *  Read a line from the keyboard
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  *  Read a character from the input line
00538  */
00539 
00540 static char get_char(void)
00541 {
00542         return *in_ptr++;
00543 }
00544 
00545 
00546 /*
00547  *  Stuff back a character into the input line
00548  */
00549 
00550 static void put_back(char c)
00551 {
00552         *(--in_ptr) = c;
00553 }
00554 
00555 
00556 /*
00557  *  Scanner: Get a token from the input line
00558  */
00559 
00560 static enum Token get_token(void)
00561 {
00562         char c;
00563 
00564         // Skip spaces
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         // Skip spaces
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  *  expression = term {(ADD | SUB) term}
00697  *  true: OK, false: Error
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  *  term = factor {(MUL | DIV) factor}
00732  *  true: OK, false: Error
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  *  factor = NUMBER | PC | SP | LPAREN expression RPAREN
00771  *  true: OK, false: Error
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  *  address_args = [expression] END
00820  *
00821  *  Read start to "address"
00822  *
00823  *  true: OK, false: Error
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  *  range_args = [expression] [[COMMA] expression] END
00840  *
00841  *  Read start address to "address", end address to "end_address"
00842  *
00843  *  true: OK, false: Error
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  *  instr_args = END
00870  *             | IMMED NUMBER END
00871  *             | NUMBER [COMMA (X | Y)] END
00872  *             | LPAREN NUMBER (RPAREN [COMMA Y] | COMMA X RPAREN) END
00873  *
00874  *  Read arguments of a 6510 instruction, determine address and addressing mode
00875  *
00876  *  true: OK, false: Error
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  *  Display help
01006  *  h
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  *  Display/change 6510 registers
01042  *  r [reg value]
01043  */
01044 
01045 static void registers(void)
01046 {
01047         enum Token the_reg;
01048         uint16 value16; //AEH 991113
01049         uint8 value;    //AEH 991113
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))      //AEH 991113
01062                                         return;
01063 
01064                                 value = (uint8)value16; //AEH 991113
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                 fprintf(fout, "%04lx %02lx %02lx %02lx %04lx %c%c%c%c%c%c ",
01123                         R1541.pc, R1541.a, R1541.x, R1541.y, R1541.sp,
01124                         R1541.p & 0x80 ? '1' : '0', R1541.p & 0x40 ? '1' : '0', R1541.p & 0x08 ? '1' : '0',
01125                         R1541.p & 0x04 ? '1' : '0', R1541.p & 0x02 ? '1' : '0', R1541.p & 0x01 ? '1' : '0');
01126                 */
01127                 //AEH 991113 (changed %04lx -> %04x)
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 /*              fprintf(fout, "%04lx %02lx %02lx %02lx %04lx %02lx %02lx %c%c%c%c%c%c ",
01146                         R64.pc, R64.a, R64.x, R64.y, R64.sp, R64.ddr, R64.pr,
01147                         R64.p & 0x80 ? '1' : '0', R64.p & 0x40 ? '1' : '0', R64.p & 0x08 ? '1' : '0',
01148                         R64.p & 0x04 ? '1' : '0', R64.p & 0x02 ? '1' : '0', R64.p & 0x01 ? '1' : '0');
01149 */
01150                 //AEH 991113
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  *  Memory dump
01173  *  m [start] [end]
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))  // 16 lines unless end address specified
01188                 return;
01189 
01190         do {
01191 //              fprintf(fout, "%04lx:", address);
01192                 fprintf(fout, "%04x:", address);        //AEH 991113
01193                 for (i=0; i<MEMDUMP_BPL; i++, address++) {
01194                         if (address == end_address) done = true;
01195 
01196 //                      fprintf(fout, " %02lx", byte = SAMReadByte(address));
01197                         fprintf(fout, " %02x", byte = SAMReadByte(address));    //AEH 991113
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  *  ASCII dump
01210  *  i [start] [end]
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))  // 16 lines unless end address specified
01225                 return;
01226 
01227         do {
01228 //              fprintf(fout, "%04lx:", address);
01229                 fprintf(fout, "%04x:", address);        //AEH 991113
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  *  Convert PETSCII->ASCII
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  *  Screen code dump
01259  *  n [start] [end]
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))  // 16 Zeilen unless end address specified
01274                 return;
01275 
01276         do {
01277 //              fprintf(fout, "%04lx:", address);
01278                 fprintf(fout, "%04x:", address);        //AEH 991113
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  *  Convert screen code->ASCII
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  *  Binary dump
01313  *  b [start] [end]
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))  // 8 lines unless end address specified
01324                 return;
01325 
01326         do {
01327                 if (address == end_address) done = true;
01328 
01329                 byte_to_bin(SAMReadByte(address), bin);
01330 //              fprintf(fout, "%04lx: %s\n", address++, bin);
01331                 fprintf(fout, "%04x: %s\n", address++, bin);    //AEH 991113
01332         } while (!done && !aborted());
01333 }
01334 
01335 
01336 /*
01337  *  Sprite data dump
01338  *  p [start] [end]
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))  // 21 lines unless end address specified
01350                 return;
01351 
01352         do {
01353 //              fprintf(fout, "%04lx: ", address);
01354                 fprintf(fout, "%04x: ", address);       //AEH 991113
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  *  Convert byte to binary representation
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  *  Disassemble
01384  *  d [start] [end]
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))  // 32 bytes unless end address specified
01395                 return;
01396 
01397         do {
01398 //              fprintf(fout, "%04lx:", adr = address);
01399                 fprintf(fout, "%04x:", adr = address);  //AEH 991113
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  *  Disassemble one instruction, return length
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         // Display instruction bytes in hex
01418         switch (adr_length[mode]) {
01419                 case 1:
01420 //                      fprintf(fout, " %02lx       ", op);
01421                         fprintf(fout, " %02x       ", op);      //AEH 991113
01422                         break;
01423 
01424                 case 2:
01425 //                      fprintf(fout, " %02lx %02lx    ", op, lo);
01426                         fprintf(fout, " %02x %02x    ", op, lo);        //AEH 991113
01427                         break;
01428 
01429                 case 3:
01430 //                      fprintf(fout, " %02lx %02lx %02lx ", op, lo, hi);
01431                         fprintf(fout, " %02x %02x %02x ", op, lo, hi);  //AEH 991113
01432                         break;
01433         }
01434 
01435         // Tag undocumented opcodes with an asterisk
01436         if (mnem > M_ILLEGAL)
01437                 fputc('*', fout);
01438         else
01439                 fputc(' ', fout);
01440 
01441         // Print mnemonic
01442         fprintf(fout, "%c%c%c ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem]);
01443 
01444         // Pring argument
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 //                      fprintf(fout, "#%02lx", lo);
01455                         fprintf(fout, "#%02x", lo);     //AEH 991113
01456                         break;
01457 
01458                 case A_REL:
01459 //                      fprintf(fout, "%04lx", ((adr + 2) + (int8)lo) & 0xffff);
01460                         fprintf(fout, "%04x", ((adr + 2) + (int8)lo) & 0xffff); //AEH 991113
01461                         break;
01462 
01463                 case A_ZERO:
01464 //                      fprintf(fout, "%02lx", lo);     
01465                         fprintf(fout, "%02x", lo);      //AEH 991113
01466                         break;
01467 
01468                 case A_ZEROX:
01469 //                      fprintf(fout, "%02lx,x", lo);
01470                         fprintf(fout, "%02x,x", lo);    //AEH 991113
01471                         break;
01472 
01473                 case A_ZEROY:
01474 //                      fprintf(fout, "%02lx,y", lo);
01475                         fprintf(fout, "%02x,y", lo);    //AEH 991113
01476                         break;
01477 
01478                 case A_ABS:
01479 //                      fprintf(fout, "%04lx", (hi << 8) | lo);
01480                         fprintf(fout, "%04x", (hi << 8) | lo);  //AEH 991113
01481                         break;
01482 
01483                 case A_ABSX:
01484 //                      fprintf(fout, "%04lx,x", (hi << 8) | lo);
01485                         fprintf(fout, "%04x,x", (hi << 8) | lo);        //AEH 991113
01486                         break;
01487 
01488                 case A_ABSY:
01489 //                      fprintf(fout, "%04lx,y", (hi << 8) | lo);
01490                         fprintf(fout, "%04x,y", (hi << 8) | lo);        //AEH 991113
01491                         break;
01492 
01493                 case A_IND:
01494 //                      fprintf(fout, "(%04lx)", (hi << 8) | lo);
01495                         fprintf(fout, "(%04x)", (hi << 8) | lo);        //AEH 991113
01496                         break;
01497 
01498                 case A_INDX:
01499 //                      fprintf(fout, "(%02lx,x)", lo);
01500                         fprintf(fout, "(%02x,x)", lo);  //AEH 991113
01501                         break;
01502 
01503                 case A_INDY:
01504 //                      fprintf(fout, "(%02lx),y", lo);
01505                         fprintf(fout, "(%02x),y", lo);  //AEH 991113
01506                         break;
01507         }
01508 
01509         fputc('\n', fout);
01510         return adr_length[mode];
01511 }
01512 
01513 
01514 /*
01515  *  Assemble
01516  *  a [start]
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         // Read parameters
01529         if (!address_args())
01530                 return;
01531 
01532         do {
01533 //              fprintf(fout, "%04lx> ", address);
01534                 fprintf(fout, "%04x> ", address);       //AEH 991113
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                                         // Convert A_IMPL -> A_ACCU if necessary
01550                                         if ((mode == A_IMPL) && find_opcode(mnem, A_ACCU, &opcode))
01551                                                 mode = A_ACCU;
01552 
01553                                         // Handle relative addressing seperately
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                                                 // Print disassembled line
01567 //                                              fprintf(fout, "\v%04lx:", address);
01568                                                 fprintf(fout, "\v%04x:", address);      //AEH 991113
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 //                                                              SAMWriteByte(address++, arg);
01579                                                                 SAMWriteByte(address++, (uint8)arg);    //AEH 991113
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                  // Input is terminated with a blank line
01603                         done = true;
01604         } while (!done);
01605 }
01606 
01607 
01608 /*
01609  *  Find mnemonic code to three letters
01610  *  M_ILLEGAL: No matching mnemonic found
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  *  Determine opcode of an instruction given mnemonic and addressing mode
01627  *  true: OK, false: Mnemonic can't have specified addressing mode
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  *  Show/set memory configuration
01646  *  k [config]
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 //      fprintf(fout, "Configuration: %ld\n", con & 7);
01662         fprintf(fout, "Configuration: %d\n", con & 7);  //AEH 991113
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  *  Fill
01671  *  f start end byte
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 //              SAMWriteByte(adr++, value);
01690                 SAMWriteByte(adr++, (uint8)value);      //AEH 991113
01691         } while (!done);
01692 }
01693 
01694 
01695 /*
01696  *  Compare
01697  *  c start end dest
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 //                      fprintf(fout, "%04lx ", adr);
01718                         fprintf(fout, "%04x ", adr);    //AEH 991113
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 //      fprintf(fout, "%ld byte(s) different\n", num);
01729         fprintf(fout, "%d byte(s) different\n", num);   //AEH 991113
01730 }
01731 
01732 
01733 /*
01734  *  Transfer memory
01735  *  t start end dest
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  *  Change memory
01767  *  : addr {byte}
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 //                      SAMWriteByte(adr++, val);
01780                         SAMWriteByte(adr++, (uint8)val);        //AEH 991113
01781                 else
01782                         return;
01783 }
01784 
01785 
01786 /*
01787  *  Compute and display expression
01788  *  ? expression
01789  */
01790 
01791 static void print_expr(void)
01792 {
01793         uint16 val;
01794 
01795         if (!expression(&val))
01796                 return;
01797 
01798 //      fprintf(fout, "Hex: %04lx\nDec: %lu\n", val, val);
01799         fprintf(fout, "Hex: %04x\nDec: %u\n", val, val);        //AEH 991113
01800 }
01801 
01802 
01803 /*
01804  *  Redirect output
01805  *  o [file]
01806  */
01807 
01808 static void redir_output(void)
01809 {
01810         // No argument given?
01811         if (the_token == T_END)
01812                 return;
01813 
01814         // Otherwise open file
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  *  Display interrupt vectors
01825  */
01826 
01827 static void int_vectors(void)
01828 {
01829         fprintf(fout, "        IRQ  BRK  NMI\n");
01830 //      fprintf(fout, "%d  : %04lx %04lx %04lx\n",
01831         fprintf(fout, "%d  : %04x %04x %04x\n", //AEH 991113
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 //              fprintf(fout, "Kernal: %04lx %04lx %04lx\n",
01839                 fprintf(fout, "Kernal: %04x %04x %04x\n",       //AEH 991113
01840                         SAMReadByte(0x0315) << 8 | SAMReadByte(0x0314),
01841                         SAMReadByte(0x0317) << 8 | SAMReadByte(0x0316),
01842                         SAMReadByte(0x0319) << 8 | SAMReadByte(0x0318));
01843 }
01844 
01845 
01846 /*
01847  *  Display state of custom chips
01848  */
01849 
01850 static void view_state(void)
01851 {
01852         switch (get_char()) {
01853                 case 'c':               // CIA
01854                         view_cia_state();
01855                         break;
01856 
01857                 case 's':               // SID
01858                         view_sid_state();
01859                         break;
01860 
01861                 case 'v':               // VIC
01862                         view_vic_state();
01863                         break;
01864 
01865                 case 'f':               // Floppy
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 //      fprintf(fout, " Counter : %04lx  Latch: %04lx\n", (cs.ta_hi << 8) | cs.ta_lo, cs.latcha);
01893         fprintf(fout, " Counter : %04x  Latch: %04x\n", (cs.ta_hi << 8) | cs.ta_lo, cs.latcha); //AEH 991113
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 //      fprintf(fout, " Counter : %04lx  Latch: %04lx\n", (cs.tb_hi << 8) | cs.tb_lo, cs.latchb);
01907         fprintf(fout, " Counter : %04x  Latch: %04x\n", (cs.tb_hi << 8) | cs.tb_lo, cs.latchb); //AEH 991113
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 /*      fprintf(fout, "TOD         : %lx%lx:%lx%lx:%lx%lx.%lx %s\n",
01930                 (cs.tod_hr >> 4) & 1, cs.tod_hr & 0x0f,
01931                 (cs.tod_min >> 4) & 7, cs.tod_min & 0x0f,
01932                 (cs.tod_sec >> 4) & 7, cs.tod_sec & 0x0f,
01933                 cs.tod_10ths & 0x0f, cs.tod_hr & 0x80 ? "PM" : "AM");
01934         fprintf(fout, "Alarm       : %lx%lx:%lx%lx:%lx%lx.%lx %s\n",
01935                 (cs.alm_hr >> 4) & 1, cs.alm_hr & 0x0f,
01936                 (cs.alm_min >> 4) & 7, cs.alm_min & 0x0f,
01937                 (cs.alm_sec >> 4) & 7, cs.alm_sec & 0x0f,
01938                 cs.alm_10ths & 0x0f, cs.alm_hr & 0x80 ? "PM" : "AM");
01939 */
01940         //AEH 991113 - start
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         //AEH 991113 - end
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 //      fprintf(fout, "Serial data : %02lx\n", cs.sdr);
01958         fprintf(fout, "Serial data : %02x\n", cs.sdr);  //AEH 991113
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 //      fprintf(fout, " Frequency  : %04lx\n", (ss.freq_hi_1 << 8) | ss.freq_lo_1);
01988         fprintf(fout, " Frequency  : %04x\n", (ss.freq_hi_1 << 8) | ss.freq_lo_1);      //AEH 991113
01989 //      fprintf(fout, " Pulse Width: %04lx\n", ((ss.pw_hi_1 & 0x0f) << 8) | ss.pw_lo_1);
01990         fprintf(fout, " Pulse Width: %04x\n", ((ss.pw_hi_1 & 0x0f) << 8) | ss.pw_lo_1); //AEH 991113
01991 //      fprintf(fout, " Env. (ADSR): %lx %lx %lx %lx\n", ss.AD_1 >> 4, ss.AD_1 & 0x0f, ss.SR_1 >> 4, ss.SR_1 & 0x0f);
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);       //AEH 991113
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 //      fprintf(fout, " Frequency  : %04lx\n", (ss.freq_hi_2 << 8) | ss.freq_lo_2);
02001 //      fprintf(fout, " Pulse Width: %04lx\n", ((ss.pw_hi_2 & 0x0f) << 8) | ss.pw_lo_2);
02002         fprintf(fout, " Frequency  : %04x\n", (ss.freq_hi_2 << 8) | ss.freq_lo_2);              //AEH 991113
02003         fprintf(fout, " Pulse Width: %04x\n", ((ss.pw_hi_2 & 0x0f) << 8) | ss.pw_lo_2); //AEH 991113
02004 //      fprintf(fout, " Env. (ADSR): %lx %lx %lx %lx\n", ss.AD_2 >> 4, ss.AD_2 & 0x0f, ss.SR_2 >> 4, ss.SR_2 & 0x0f);
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);       //AEH 991113
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 //      fprintf(fout, " Frequency  : %04lx\n", (ss.freq_hi_3 << 8) | ss.freq_lo_3);
02014 //      fprintf(fout, " Pulse Width: %04lx\n", ((ss.pw_hi_3 & 0x0f) << 8) | ss.pw_lo_3);
02015         fprintf(fout, " Frequency  : %04x\n", (ss.freq_hi_3 << 8) | ss.freq_lo_3);              //AEH 991113
02016         fprintf(fout, " Pulse Width: %04x\n", ((ss.pw_hi_3 & 0x0f) << 8) | ss.pw_lo_3); //AEH 991113
02017 //      fprintf(fout, " Env. (ADSR): %lx %lx %lx %lx\n", ss.AD_3 >> 4, ss.AD_3 & 0x0f, ss.SR_3 >> 4, ss.SR_3 & 0x0f);
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);       //AEH 991113
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 //      fprintf(fout, " Frequency: %04lx\n", (ss.fc_hi << 3) | (ss.fc_lo & 0x07));
02027         fprintf(fout, " Frequency: %04x\n", (ss.fc_hi << 3) | (ss.fc_lo & 0x07));       //AEH 991113
02028 //      fprintf(fout, " Resonance: %lx\n", ss.res_filt >> 4);
02029         fprintf(fout, " Resonance: %x\n", ss.res_filt >> 4);    //AEH 991113
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 //      fprintf(fout, "\n Volume   : %lx\n", ss.mode_vol & 0x0f);
02038         fprintf(fout, "\n Volume   : %x\n", ss.mode_vol & 0x0f);        //AEH 991113
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 //      fprintf(fout, "Raster line       : %04lx\n", vs.raster | ((vs.ctrl1 & 0x80) << 1));
02061 //      fprintf(fout, "IRQ raster line   : %04lx\n\n", vs.irq_raster);
02062 
02063         fprintf(fout, "Raster line       : %04x\n", vs.raster | ((vs.ctrl1 & 0x80) << 1));              //AEH 991113
02064         fprintf(fout, "IRQ raster line   : %04x\n\n", vs.irq_raster);                                                   //AEH 991113
02065 
02066 /*      fprintf(fout, "X scroll          : %ld\n", vs.ctrl2 & 7);
02067         fprintf(fout, "Y scroll          : %ld\n", vs.ctrl1 & 7);
02068         fprintf(fout, "Horizontal border : %ld columns\n", vs.ctrl2 & 8 ? 40 : 38);
02069         fprintf(fout, "Vertical border   : %ld rows\n\n", vs.ctrl1 & 8 ? 25 : 24);
02070 */
02071         //AEH 991113 - start
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         //AEH 991113 - end
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 //      fprintf(fout, "Video counter     : %04lx\n", vs.vc);
02109 //      fprintf(fout, "Video counter base: %04lx\n", vs.vc_base);
02110         fprintf(fout, "Video counter     : %04x\n", vs.vc);                     //AEH 991113
02111         fprintf(fout, "Video counter base: %04x\n", vs.vc_base);        //AEH 991113
02112 //      fprintf(fout, "Row counter       : %ld\n\n", vs.rc);
02113         fprintf(fout, "Row counter       : %d\n\n", vs.rc);     //AEH 991113
02114 
02115 /*      fprintf(fout, "VIC bank          : %04lx-%04lx\n", vs.bank_base, vs.bank_base + 0x3fff);
02116         fprintf(fout, "Video matrix base : %04lx\n", vs.matrix_base);
02117         fprintf(fout, "Character base    : %04lx\n", vs.char_base);
02118         fprintf(fout, "Bitmap base       : %04lx\n\n", vs.bitmap_base);
02119 */
02120         //AEH 991113 - start
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         //AEH 991113 - end
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 //      fprintf(fout, "Data   : %04lx   %04lx   %04lx   %04lx   %04lx   %04lx   %04lx   %04lx\n",
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 //      fprintf(fout, "MC     : %02lx     %02lx     %02lx     %02lx     %02lx     %02lx     %02lx     %02lx\n",
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  *  Load data
02226  *  l start "file"
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  *  Save data
02258  *  s start end "file"
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 }

Generated on Tue Feb 8 04:08:08 2005 for E32frodo by doxygen 1.3.3