Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
4577 lines (3997 sloc)
136 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| ** Oricutron | |
| ** Copyright (C) 2009-2014 Peter Gordon | |
| ** | |
| ** This program is free software; you can redistribute it and/or | |
| ** modify it under the terms of the GNU General Public License | |
| ** as published by the Free Software Foundation, version 2 | |
| ** of the License. | |
| ** | |
| ** This program is distributed in the hope that it will be useful, | |
| ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| ** GNU General Public License for more details. | |
| ** | |
| ** You should have received a copy of the GNU General Public License | |
| ** along with this program; if not, write to the Free Software | |
| ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| ** | |
| ** Monitor/Debugger | |
| */ | |
| #define MAX_CONS_INPUT 127 // Max line length in console | |
| #define MAX_ASM_INPUT 36 | |
| #define CONS_WIDTH 46 // Actual console width for input | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdarg.h> | |
| #include <ctype.h> | |
| #include "system.h" | |
| #undef REG_PC // MorphOS should not define REG_PC | |
| #define REG_PC _REG_PC | |
| #include "6502.h" | |
| #include "via.h" | |
| #include "8912.h" | |
| #include "gui.h" | |
| #include "disk.h" | |
| #include "monitor.h" | |
| #include "6551.h" | |
| #include "machine.h" | |
| #include "ula.h" | |
| #include "tape.h" | |
| #include "snapshot.h" | |
| #define LOG_DEBUG 0 | |
| #if LOG_DEBUG | |
| #if defined(__amigaos4__) || defined(__MORPHOS__) | |
| static char *debug_logname = "RAM:debug.log"; | |
| #else | |
| static char *debug_logname = "debug_log.txt"; | |
| #endif | |
| FILE *debug_logfile = NULL; | |
| #endif | |
| struct disinf | |
| { | |
| char *name; | |
| int amode; | |
| }; | |
| struct asminf | |
| { | |
| char *name; | |
| short imp, imm, zp, zpx, zpy, abs, abx, aby, zix, ziy, rel, ind; | |
| }; | |
| struct click | |
| { | |
| int x, y, time; | |
| }; | |
| static struct click leftclick[2]; | |
| extern struct textzone *tz[]; | |
| extern char vsptmp[]; | |
| extern char snappath[], filetmp[]; | |
| extern SDL_bool refreshstatus; | |
| static char distmp[128]; | |
| static unsigned short disaddrs[10]; | |
| static char ibuf[128], lastcmd; | |
| static char history[10][128]; | |
| static int ilen, iloff=0, cursx, histu=0, histp=-1; | |
| static unsigned short mon_addr, mon_asmmode = SDL_FALSE; | |
| static SDL_bool kshifted = SDL_FALSE, updatepreview = SDL_FALSE; | |
| static int helpcount=0; | |
| static int memory_search_pos=0; | |
| static struct symboltable defaultsyms; | |
| char mon_bpmsg[80]; | |
| static SDL_bool mw_split = SDL_FALSE; | |
| static int mw_which = 0; | |
| static unsigned short mw_addr[2]; | |
| static int mw_mode=0, mw_koffs=0; | |
| static char mw_ibuf[8]; | |
| static unsigned char mwatch_old[65536]; | |
| static SDL_bool mwatch_oldvalid = SDL_FALSE; | |
| static struct m6502 cpu_old; | |
| static int vidraster_old, frames_old; | |
| static SDL_bool cpu_oldvalid = SDL_FALSE; | |
| static struct ay8912 ay_old; | |
| static SDL_bool ay_oldvalid = SDL_FALSE; | |
| static struct via via_old; | |
| static SDL_bool via_oldvalid = SDL_FALSE; | |
| static struct via via2_old; | |
| static SDL_bool via2_oldvalid = SDL_FALSE; | |
| static SDL_bool modified = SDL_FALSE; | |
| static uint16_t memory_search[0x9800-0x0500]; | |
| static int memory_hits= 0; | |
| // auto repeat commands | |
| enum | |
| { | |
| ARPT_NULL = 0, | |
| ARPT_SEARCH = 1, | |
| ARPT_HELP = '?', | |
| ARPT_MEMORY = 'm', | |
| ARPT_DISASM = 'd', | |
| ARPT_ASSEM = 'a', | |
| ARPT_QUIT = 'q', | |
| }; | |
| // 12345678901 12345678 | |
| static struct msym defsym_tele[] = { { 0x0300, 0, "VIA_IORB" , "VIA_IORB" , "VIA_IORB" }, | |
| { 0x0301, 0, "VIA_IORA" , "VIA_IORA" , "VIA_IORA" }, | |
| { 0x0302, 0, "VIA_DDRB" , "VIA_DDRB" , "VIA_DDRB" }, | |
| { 0x0303, 0, "VIA_DDRA" , "VIA_DDRA" , "VIA_DDRA" }, | |
| { 0x0304, 0, "VIA_T1C_L" , "VIA_T1C\x16", "VIA_T1C_L" }, | |
| { 0x0305, 0, "VIA_T1C_H" , "VIA_T1C\x16", "VIA_T1C_H" }, | |
| { 0x0306, 0, "VIA_T1L_L" , "VIA_T1L\x16", "VIA_T1L_L" }, | |
| { 0x0307, 0, "VIA_T1L_H" , "VIA_T1L\x16", "VIA_T1L_H" }, | |
| { 0x0308, 0, "VIA_T2C_L" , "VIA_T2C\x16", "VIA_T2C_L" }, | |
| { 0x0309, 0, "VIA_T2C_H" , "VIA_T2C\x16", "VIA_T2C_H" }, | |
| { 0x030A, 0, "VIA_SR" , "VIA_SR" , "VIA_SR" }, | |
| { 0x030B, 0, "VIA_ACR" , "VIA_ACR" , "VIA_ACR" }, | |
| { 0x030C, 0, "VIA_PCR" , "VIA_PCR" , "VIA_PCR" }, | |
| { 0x030D, 0, "VIA_IFR" , "VIA_IFR" , "VIA_IFR" }, | |
| { 0x030E, 0, "VIA_IER" , "VIA_IER" , "VIA_IER" }, | |
| { 0x030F, 0, "VIA_IORA2" , "VIA_IORA2" , "VIA_IORA2" }, | |
| { 0x0310, 0, "WD17_COMMA\x16", "WD17_CO\x16", "WD17_COMMAND" }, | |
| { 0x0311, 0, "WD17_TRACK\x16", "WD17_TR\x16", "WD17_TRACK" }, | |
| { 0x0312, 0, "WD17_SECTO\x16", "WD17_SE\x16", "WD17_SECTOR" }, | |
| { 0x0313, 0, "WD17_DATA" , "WD17_DA\x16", "WD17_DATA" }, | |
| { 0x0314, 0, "MDSC_STATUS" , "MDSC_ST\x16", "MDSC_STATUS" }, | |
| { 0x0318, 0, "MDSC_DRQ" , "MDSC_DR\x16", "MDSC_DRQ" }, | |
| { 0x031c, 0, "ACIA_DATA" , "ACIA_DA\x16", "ACIA_DATA" }, | |
| { 0x031d, 0, "ACIA_STATUS" , "ACIA_ST\x16", "ACIA_STATUS" }, | |
| { 0x031e, 0, "ACIA_COMMA\x16", "ACIA_CO\x16", "ACIA_COMMAND" }, | |
| { 0x031f, 0, "ACIA_CONTR\x16", "ACIA_CO\x16", "ACIA_CONTROL" }, | |
| { 0x0320, 0, "VIA2_IORB" , "VIA2_IORB" , "VIA2_IORB" }, | |
| { 0x0321, 0, "VIA2_IORA" , "VIA2_IORA" , "VIA2_IORA" }, | |
| { 0x0322, 0, "VIA2_DDRB" , "VIA2_DDRB" , "VIA2_DDRB" }, | |
| { 0x0323, 0, "VIA2_DDRA" , "VIA2_DDRA" , "VIA2_DDRA" }, | |
| { 0x0324, 0, "VIA2_T1C_L" , "VIA2_T1\x16", "VIA2_T1C_L" }, | |
| { 0x0325, 0, "VIA2_T1C_H" , "VIA2_T1\x16", "VIA2_T1C_H" }, | |
| { 0x0326, 0, "VIA2_T1L_L" , "VIA2_T1\x16", "VIA2_T1L_L" }, | |
| { 0x0327, 0, "VIA2_T1L_H" , "VIA2_T1\x16", "VIA2_T1L_H" }, | |
| { 0x0328, 0, "VIA2_T2C_L" , "VIA2_T2\x16", "VIA2_T2C_L" }, | |
| { 0x0329, 0, "VIA2_T2C_H" , "VIA2_T2\x16", "VIA2_T2C_H" }, | |
| { 0x032A, 0, "VIA2_SR" , "VIA2_SR" , "VIA2_SR" }, | |
| { 0x032B, 0, "VIA2_ACR" , "VIA2_ACR" , "VIA2_ACR" }, | |
| { 0x032C, 0, "VIA2_PCR" , "VIA2_PCR" , "VIA2_PCR" }, | |
| { 0x032D, 0, "VIA2_IFR" , "VIA2_IFR" , "VIA2_IFR" }, | |
| { 0x032E, 0, "VIA2_IER" , "VIA2_IER" , "VIA2_IER" }, | |
| { 0x032F, 0, "VIA2_IORA2" , "VIA2_IO\x16", "VIA2_IORA2" }, | |
| { 0xc000, 0, "BankedArea" , "BankedA\x16", "BankedArea" } }; | |
| // 12345678901 12345678 | |
| static struct msym defsym_atmos[] = { { 0x0300, 0, "VIA_IORB" , "VIA_IORB" , "VIA_IORB" }, | |
| { 0x0301, 0, "VIA_IORA" , "VIA_IORA" , "VIA_IORA" }, | |
| { 0x0302, 0, "VIA_DDRB" , "VIA_DDRB" , "VIA_DDRB" }, | |
| { 0x0303, 0, "VIA_DDRA" , "VIA_DDRA" , "VIA_DDRA" }, | |
| { 0x0304, 0, "VIA_T1C_L" , "VIA_T1C\x16", "VIA_T1C_L" }, | |
| { 0x0305, 0, "VIA_T1C_H" , "VIA_T1C\x16", "VIA_T1C_H" }, | |
| { 0x0306, 0, "VIA_T1L_L" , "VIA_T1L\x16", "VIA_T1L_L" }, | |
| { 0x0307, 0, "VIA_T1L_H" , "VIA_T1L\x16", "VIA_T1L_H" }, | |
| { 0x0308, 0, "VIA_T2C_L" , "VIA_T2C\x16", "VIA_T2C_L" }, | |
| { 0x0309, 0, "VIA_T2C_H" , "VIA_T2C\x16", "VIA_T2C_H" }, | |
| { 0x030A, 0, "VIA_SR" , "VIA_SR" , "VIA_SR" }, | |
| { 0x030B, 0, "VIA_ACR" , "VIA_ACR" , "VIA_ACR" }, | |
| { 0x030C, 0, "VIA_PCR" , "VIA_PCR" , "VIA_PCR" }, | |
| { 0x030D, 0, "VIA_IFR" , "VIA_IFR" , "VIA_IFR" }, | |
| { 0x030E, 0, "VIA_IER" , "VIA_IER" , "VIA_IER" }, | |
| { 0x030F, 0, "VIA_IORA2" , "VIA_IORA2" , "VIA_IORA2" }, | |
| { 0xc000, SYMF_ROMDIS0, "ROMStart" , "ROMStart" , "ROMStart" }, | |
| { 0xc000, SYMF_ROMDIS1, "Overlay" , "Overlay" , "Overlay" } }; | |
| enum | |
| { | |
| MSHOW_VIA=0, | |
| MSHOW_VIA2, | |
| MSHOW_AY, | |
| MSHOW_DISK, | |
| MSHOW_LAST | |
| }; | |
| enum | |
| { | |
| CSHOW_CONSOLE=0, | |
| CSHOW_DEBUG, | |
| CSHOW_MWATCH, | |
| CSHOW_LAST | |
| }; | |
| static int mshow, cshow; | |
| enum | |
| { | |
| REG_A=0, | |
| REG_X, | |
| REG_Y, | |
| REG_PC, | |
| REG_SP, | |
| REG_VIA_PCR, | |
| REG_VIA_ACR, | |
| REG_VIA_SR, | |
| REG_VIA_IFR, | |
| REG_VIA_IER, | |
| REG_VIA_IRA, | |
| REG_VIA_ORA, | |
| REG_VIA_DDRA, | |
| REG_VIA_IRB, | |
| REG_VIA_ORB, | |
| REG_VIA_DDRB, | |
| REG_VIA_T1L, | |
| REG_VIA_T1C, | |
| REG_VIA_T2L, | |
| REG_VIA_T2C, | |
| REG_VIA_CA1, | |
| REG_VIA_CA2, | |
| REG_VIA_CB1, | |
| REG_VIA_CB2 | |
| }; | |
| enum | |
| { | |
| AM_IMP=0, | |
| AM_IMM, | |
| AM_ZP, | |
| AM_ZPX, | |
| AM_ZPY, | |
| AM_ABS, | |
| AM_ABX, | |
| AM_ABY, | |
| AM_ZIX, | |
| AM_ZIY, | |
| AM_REL, | |
| AM_IND | |
| }; | |
| #define AMF_IMP (1<<AM_IMP) | |
| #define AMF_IMM (1<<AM_IMM) | |
| #define AMF_ZP (1<<AM_ZP) | |
| #define AMF_ZPX (1<<AM_ZPX) | |
| #define AMF_ZPY (1<<AM_ZPY) | |
| #define AMF_ABS (1<<AM_ABS) | |
| #define AMF_ABX (1<<AM_ABX) | |
| #define AMF_ABY (1<<AM_ABY) | |
| #define AMF_ZIX (1<<AM_ZIX) | |
| #define AMF_ZIY (1<<AM_ZIY) | |
| #define AMF_REL (1<<AM_REL) | |
| #define AMF_IND (1<<AM_IND) | |
| // imp imm zp zpx zpy abs abx aby zix ziy rel ind | |
| static struct asminf asmtab[] = { { "BRK", -1, 0x00, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "ORA", -1, 0x09, 0x05, 0x15, -1, 0x0d, 0x1d, 0x19, 0x01, 0x11, -1, -1 }, | |
| { "ASL", 0x0a, -1, 0x06, 0x16, -1, 0x0e, 0x1e, -1, -1, -1, -1, -1 }, | |
| { "PHP", 0x08, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "BPL", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x10, -1 }, | |
| { "CLC", 0x18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "JSR", -1, -1, -1, -1, -1, 0x20, -1, -1, -1, -1, -1, -1 }, | |
| { "AND", -1, 0x29, 0x25, 0x35, -1, 0x2d, 0x3d, 0x39, 0x21, 0x31, -1, -1 }, | |
| { "BIT", -1, -1, 0x24, -1, -1, 0x2c, -1, -1, -1, -1, -1, -1 }, | |
| { "ROL", 0x2a, -1, 0x26, 0x36, -1, 0x2e, 0x3e, -1, -1, -1, -1, -1 }, | |
| { "PLP", 0x28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "BMI", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x30, -1 }, | |
| { "SEC", 0x38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "RTI", 0x40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "EOR", -1, 0x49, 0x45, 0x55, -1, 0x4d, 0x5d, 0x59, 0x41, 0x51, -1, -1 }, | |
| { "LSR", 0x4a, -1, 0x46, 0x56, -1, 0x4e, 0x5e, -1, -1, -1, -1, -1 }, | |
| { "PHA", 0x48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "JMP", -1, -1, -1, -1, -1, 0x4c, -1, -1, -1, -1, -1, 0x6c }, | |
| { "BVC", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x50, -1 }, | |
| { "CLI", 0x58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "RTS", 0x60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "ADC", -1, 0x69, 0x65, 0x75, -1, 0x6d, 0x7d, 0x79, 0x61, 0x71, -1, -1 }, | |
| { "ROR", 0x6a, -1, 0x66, 0x76, -1, 0x6e, 0x7e, -1, -1, -1, -1, -1 }, | |
| { "PLA", 0x68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "BVS", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x70, -1 }, | |
| { "SEI", 0x78, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "STY", -1, -1, 0x84, 0x94, -1, 0x8c, -1, -1, -1, -1, -1, -1 }, | |
| { "STA", -1, -1, 0x85, 0x95, -1, 0x8d, 0x9d, 0x99, 0x81, 0x91, -1, -1 }, | |
| { "STX", -1, -1, 0x86, 0x96, -1, 0x8e, -1, -1, -1, -1, -1, -1 }, | |
| { "DEY", 0x88, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "TXA", 0x8a, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "BCC", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x90, -1 }, | |
| { "TYA", 0x98, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "TXS", 0x9a, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "LDY", -1, 0xa0, 0xa4, 0xb4, -1, 0xac, 0xbc, -1, -1, -1, -1, -1 }, | |
| { "LDA", -1, 0xa9, 0xa5, 0xb5, -1, 0xad, 0xbd, 0xb9, 0xa1, 0xb1, -1, -1 }, | |
| { "LDX", -1, 0xa2, 0xa6, -1, 0xb6, 0xae, -1, 0xbe, -1, -1, -1, -1 }, | |
| { "TAY", 0xa8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "TAX", 0xaa, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "BCS", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xb0, -1 }, | |
| { "CLV", 0xb8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "TSX", 0xba, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "CPY", -1, 0xc0, 0xc4, -1, -1, 0xcc, -1, -1, -1, -1, -1, -1 }, | |
| { "CMP", -1, 0xc9, 0xc5, 0xd5, -1, 0xcd, 0xdd, 0xd9, 0xc1, 0xd1, -1, -1 }, | |
| { "DEC", -1, -1, 0xc6, 0xd6, -1, 0xce, 0xde, -1, 0xc1, -1, -1, -1 }, | |
| { "INY", 0xc8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "DEX", 0xca, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "BNE", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xd0, -1 }, | |
| { "CLD", 0xd8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "CPX", -1, 0xe0, 0xe4, -1, -1, 0xec, -1, -1, -1, -1, -1, -1 }, | |
| { "SBC", -1, 0xe9, 0xe5, 0xf5, -1, 0xed, 0xfd, 0xf9, 0xe1, 0xf1, -1, -1 }, | |
| { "INC", -1, -1, 0xe6, 0xf6, -1, 0xee, 0xfe, -1, -1, -1, -1, -1 }, | |
| { "INX", 0xe8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "NOP", 0xea, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "BEQ", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xf0, -1 }, | |
| { "SED", 0xf8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| // Illegal opcodes | |
| // imp imm zp zpx zpy abs abx aby zix ziy rel ind | |
| { "ANC", -1, 0x0b, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "SAX", -1, -1, 0x87, -1, 0x97, 0x8f, -1, -1, 0x83, -1, -1, -1 }, | |
| { "ARR", -1, 0x6b, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "ALR", -1, 0x4b, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "LAX", -1, 0xab, 0xa7, -1, 0xb7, 0xaf, -1, 0xbf, 0xa3, 0xb3, -1, -1 }, | |
| { "AHX", -1, -1, -1, -1, -1, -1, -1, 0x9f, -1, 0x93, -1, -1 }, | |
| { "AXS", -1, 0xcb, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "DCP", -1, -1, 0xc7, 0xd7, -1, 0xcf, 0xdf, 0xdb, 0xc3, 0xd3, -1, -1 }, | |
| { "DOP", -1, 0x80, 0x04, 0x14, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "ISC", -1, -1, 0xe7, 0xf7, -1, 0xef, 0xff, 0xfb, 0xe3, 0xf3, -1, -1 }, | |
| { "JAM", 0x02, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "LAS", -1, -1, -1, -1, -1, -1, -1, 0xbb, -1, -1, -1, -1 }, | |
| { "RLA", -1, -1, 0x27, 0x37, -1, 0x2f, 0x3f, 0x3b, 0x23, 0x33, -1, -1 }, | |
| { "RRA", -1, -1, 0x67, 0x77, -1, 0x6f, 0x7f, 0x7b, 0x63, 0x73, -1, -1 }, | |
| { "SLO", -1, -1, 0x07, 0x17, -1, 0x0f, 0x1f, 0x1b, 0x03, 0x13, -1, -1 }, | |
| { "SRE", -1, -1, 0x47, 0x57, -1, 0x4f, 0x5f, 0x5b, 0x43, 0x53, -1, -1 }, | |
| { "SHX", -1, -1, -1, -1, -1, -1, -1, 0x9e, -1, -1, -1, -1 }, | |
| { "SHY", -1, -1, -1, -1, -1, -1, 0x9c, -1, -1, -1, -1, -1 }, | |
| { "TOP", -1, -1, -1, -1, -1, 0x0c, 0x1c, -1, -1, -1, -1, -1 }, | |
| { "XAA", -1, 0x8b, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { "TAS", -1, 0x9b, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, | |
| { NULL, } }; | |
| static struct disinf distab[] = { { "BRK", AM_IMM }, // 00 | |
| { "ORA", AM_ZIX }, // 01 | |
| { "JAM", AM_IMP }, // 02 (illegal) | |
| { "SLO", AM_ZIX }, // 03 (illegal) | |
| { "DOP", AM_ZP }, // 04 (illegal) | |
| { "ORA", AM_ZP }, // 05 | |
| { "ASL", AM_ZP }, // 06 | |
| { "SLO", AM_ZP }, // 07 (illegal) | |
| { "PHP", AM_IMP }, // 08 | |
| { "ORA", AM_IMM }, // 09 | |
| { "ASL", AM_IMP }, // 0A | |
| { "ANC", AM_IMM }, // 0B (illegal) | |
| { "TOP", AM_IMP }, // 0C (illegal) | |
| { "ORA", AM_ABS }, // 0D | |
| { "ASL", AM_ABS }, // 0E | |
| { "SLO", AM_ABS }, // 0F (illegal) | |
| { "BPL", AM_REL }, // 10 | |
| { "ORA", AM_ZIY }, // 11 | |
| { "JAM", AM_IMP }, // 12 (illegal) | |
| { "SLO", AM_ZIY }, // 13 (illegal) | |
| { "DOP", AM_ZPX }, // 14 (illegal) | |
| { "ORA", AM_ZPX }, // 15 | |
| { "ASL", AM_ZPX }, // 16 | |
| { "SLO", AM_ZPX }, // 17 (illegal) | |
| { "CLC", AM_IMP }, // 18 | |
| { "ORA", AM_ABY }, // 19 | |
| { "NOP", AM_IMP }, // 1A (illegal) | |
| { "SLO", AM_ABY }, // 1B (illegal) | |
| { "TOP", AM_ABX }, // 1C (illegal) | |
| { "ORA", AM_ABX }, // 1D | |
| { "ASL", AM_ABX }, // 1E | |
| { "SLO", AM_IMP }, // 1F (illegal) | |
| { "JSR", AM_ABS }, // 20 | |
| { "AND", AM_ZIX }, // 21 | |
| { "JAM", AM_IMP }, // 22 (illegal) | |
| { "RLA", AM_ZIX }, // 23 (illegal) | |
| { "BIT", AM_ZP }, // 24 | |
| { "AND", AM_ZP }, // 25 | |
| { "ROL", AM_ZP }, // 26 | |
| { "RLA", AM_ZP }, // 27 (illegal) | |
| { "PLP", AM_IMP }, // 28 | |
| { "AND", AM_IMM }, // 29 | |
| { "ROL", AM_IMP }, // 2A | |
| { "ANC", AM_IMP }, // 2B (illegal) | |
| { "BIT", AM_ABS }, // 2C | |
| { "AND", AM_ABS }, // 2D | |
| { "ROL", AM_ABS }, // 2E | |
| { "RLA", AM_ABS }, // 2F (illegal) | |
| { "BMI", AM_REL }, // 30 | |
| { "AND", AM_ZIY }, // 31 | |
| { "JAM", AM_IMP }, // 32 (illegal) | |
| { "RLA", AM_ZIY }, // 33 (illegal) | |
| { "DOP", AM_ZPX }, // 34 (illegal) | |
| { "AND", AM_ZPX }, // 35 | |
| { "ROL", AM_ZPX }, // 36 | |
| { "RLA", AM_ZPX }, // 37 (illegal) | |
| { "SEC", AM_IMP }, // 38 | |
| { "AND", AM_ABY }, // 39 | |
| { "NOP", AM_IMP }, // 3A (illegal) | |
| { "RLA", AM_ABY }, // 3B (illegal) | |
| { "TOP", AM_ABX }, // 3C (illegal) | |
| { "AND", AM_ABX }, // 3D | |
| { "ROL", AM_ABX }, // 3E | |
| { "RLA", AM_ABX }, // 3F (illegal) | |
| { "RTI", AM_IMP }, // 40 | |
| { "EOR", AM_ZIX }, // 41 | |
| { "JAM", AM_IMP }, // 42 (illegal) | |
| { "SRE", AM_ZIX }, // 43 (illegal) | |
| { "DOP", AM_ZP }, // 44 (illegal) | |
| { "EOR", AM_ZP }, // 45 | |
| { "LSR", AM_ZP }, // 46 | |
| { "SRE", AM_ZP }, // 47 (illegal) | |
| { "PHA", AM_IMP }, // 48 | |
| { "EOR", AM_IMM }, // 49 | |
| { "LSR", AM_IMP }, // 4A | |
| { "ALR", AM_IMM }, // 4B (illegal) | |
| { "JMP", AM_ABS }, // 4C | |
| { "EOR", AM_ABS }, // 4D | |
| { "LSR", AM_ABS }, // 4E | |
| { "SRE", AM_ABS }, // 4F (illegal) | |
| { "BVC", AM_REL }, // 50 | |
| { "EOR", AM_ZIY }, // 51 | |
| { "JAM", AM_IMP }, // 52 (illegal) | |
| { "SRE", AM_ZIY }, // 53 (illegal) | |
| { "DOP", AM_ZPX }, // 54 (illegal) | |
| { "EOR", AM_ZPX }, // 55 | |
| { "LSR", AM_ZPX }, // 56 | |
| { "SRE", AM_ZPX }, // 57 (illegal) | |
| { "CLI", AM_IMP }, // 58 | |
| { "EOR", AM_ABY }, // 59 | |
| { "NOP", AM_IMP }, // 5A (illegal) | |
| { "SRE", AM_ABY }, // 5B (illegal) | |
| { "TOP", AM_ABX }, // 5C (illegal) | |
| { "EOR", AM_ABX }, // 5D | |
| { "LSR", AM_ABX }, // 5E | |
| { "SRE", AM_ABX }, // 5F (illegal) | |
| { "RTS", AM_IMP }, // 60 | |
| { "ADC", AM_ZIX }, // 61 | |
| { "JAM", AM_IMP }, // 62 (illegal) | |
| { "RRA", AM_ZIX }, // 63 (illegal) | |
| { "DOP", AM_IMP }, // 64 (illegal) | |
| { "ADC", AM_ZP }, // 65 | |
| { "ROR", AM_ZP }, // 66 | |
| { "RRA", AM_ZP }, // 67 (illegal) | |
| { "PLA", AM_IMP }, // 68 | |
| { "ADC", AM_IMM }, // 69 | |
| { "ROR", AM_IMP }, // 6A | |
| { "ARR", AM_IMM }, // 6B (illegal) | |
| { "JMP", AM_IND }, // 6C | |
| { "ADC", AM_ABS }, // 6D | |
| { "ROR", AM_ABS }, // 6E | |
| { "RRA", AM_ABS }, // 6F (illegal) | |
| { "BVS", AM_REL }, // 70 | |
| { "ADC", AM_ZIY }, // 71 | |
| { "JAM", AM_IMP }, // 72 (illegal) | |
| { "RRA", AM_ZIY }, // 73 (illegal) | |
| { "DOP", AM_ZPX }, // 74 (illegal) | |
| { "ADC", AM_ZPX }, // 75 | |
| { "ROR", AM_ZPX }, // 76 | |
| { "RRA", AM_ZPX }, // 77 | |
| { "SEI", AM_IMP }, // 78 | |
| { "ADC", AM_ABY }, // 79 | |
| { "NOP", AM_IMP }, // 7A (illegal) | |
| { "RRA", AM_ABY }, // 7B (illegal) | |
| { "TOP", AM_ABX }, // 7C (illegal) | |
| { "ADC", AM_ABX }, // 7D | |
| { "ROR", AM_ABX }, // 7E | |
| { "RRA", AM_ABX }, // 7F (illegal) | |
| { "DOP", AM_IMM }, // 80 (illegal) | |
| { "STA", AM_ZIX }, // 81 | |
| { "DOP", AM_IMM }, // 82 (illegal) | |
| { "SAX", AM_ZIX }, // 83 (illegal) | |
| { "STY", AM_ZP }, // 84 | |
| { "STA", AM_ZP }, // 85 | |
| { "STX", AM_ZP }, // 86 | |
| { "SAX", AM_ZP }, // 87 (illegal) | |
| { "DEY", AM_IMP }, // 88 | |
| { "DOP", AM_IMM }, // 89 (illegal) | |
| { "TXA", AM_IMP }, // 8A | |
| { "XAA", AM_IMM }, // 8B (illegal, unstable) | |
| { "STY", AM_ABS }, // 8C | |
| { "STA", AM_ABS }, // 8D | |
| { "STX", AM_ABS }, // 8E | |
| { "SAX", AM_ABS }, // 8F (illegal) | |
| { "BCC", AM_REL }, // 90 | |
| { "STA", AM_ZIY }, // 91 | |
| { "JAM", AM_IMP }, // 92 (illegal) | |
| { "AHX", AM_ZIY }, // 93 (illegal, unstable) | |
| { "STY", AM_ZPX }, // 94 | |
| { "STA", AM_ZPX }, // 95 | |
| { "STX", AM_ZPY }, // 96 | |
| { "SAX", AM_ZPY }, // 97 (illegal) | |
| { "TYA", AM_IMP }, // 98 | |
| { "STA", AM_ABY }, // 99 | |
| { "TXS", AM_IMP }, // 9A | |
| { "TAS", AM_IMM }, // 9B (illegal0 | |
| { "SHY", AM_ABY }, // 9C (illegal, unstable) | |
| { "STA", AM_ABX }, // 9D | |
| { "SHX", AM_ABX }, // 9E (illegal, unstable) | |
| { "AHX", AM_ABY }, // 9F (illegal, unstable) | |
| { "LDY", AM_IMM }, // A0 | |
| { "LDA", AM_ZIX }, // A1 | |
| { "LDX", AM_IMM }, // A2 | |
| { "LAX", AM_ZIX }, // A3 (illegal) | |
| { "LDY", AM_ZP }, // A4 | |
| { "LDA", AM_ZP }, // A5 | |
| { "LDX", AM_ZP }, // A6 | |
| { "LAX", AM_ZP }, // A7 (illegal) | |
| { "TAY", AM_IMP }, // A8 | |
| { "LDA", AM_IMM }, // A9 | |
| { "TAX", AM_IMP }, // AA | |
| { "LAX", AM_IMM }, // AB (illegal, unstable) | |
| { "LDY", AM_ABS }, // AC | |
| { "LDA", AM_ABS }, // AD | |
| { "LDX", AM_ABS }, // AE | |
| { "LAX", AM_ABS }, // AF (illegal) | |
| { "BCS", AM_REL }, // B0 | |
| { "LDA", AM_ZIY }, // B1 | |
| { "JAM", AM_IMP }, // B2 (illegal) | |
| { "LAX", AM_ZIY }, // B3 (illegal) | |
| { "LDY", AM_ZPX }, // B4 | |
| { "LDA", AM_ZPX }, // B5 | |
| { "LDX", AM_ZPY }, // B6 | |
| { "LAX", AM_ZPY }, // B7 (illegal) | |
| { "CLV", AM_IMP }, // B8 | |
| { "LDA", AM_ABY }, // B9 | |
| { "TSX", AM_IMP }, // BA | |
| { "LAS", AM_IMP }, // BB (illegal) | |
| { "LDY", AM_ABX }, // BC | |
| { "LDA", AM_ABX }, // BD | |
| { "LDX", AM_ABY }, // BE | |
| { "LAX", AM_ABY }, // BF (illegal) | |
| { "CPY", AM_IMM }, // C0 | |
| { "CMP", AM_ZIX }, // C1 | |
| { "DOP", AM_IMP }, // C2 (illegal) | |
| { "DCP", AM_ZIX }, // C3 (illegal) | |
| { "CPY", AM_ZP }, // C4 | |
| { "CMP", AM_ZP }, // C5 | |
| { "DEC", AM_ZP }, // C6 | |
| { "DCP", AM_ZP }, // C7 (illegal) | |
| { "INY", AM_IMP }, // C8 | |
| { "CMP", AM_IMM }, // C9 | |
| { "DEX", AM_IMP }, // CA | |
| { "AXS", AM_IMM }, // CB (illegal) | |
| { "CPY", AM_ABS }, // CC | |
| { "CMP", AM_ABS }, // CD | |
| { "DEC", AM_ABS }, // CE | |
| { "DCP", AM_ABS }, // CF (illegal) | |
| { "BNE", AM_REL }, // D0 | |
| { "CMP", AM_ZIY }, // D1 | |
| { "JAM", AM_IMP }, // D2 (illegal) | |
| { "DCP", AM_ZIY }, // D3 (illegal) | |
| { "DOP", AM_ZPX }, // D4 (illegal) | |
| { "CMP", AM_ZPX }, // D5 | |
| { "DEC", AM_ZPX }, // D6 | |
| { "DCP", AM_ZPX }, // D7 (illegal) | |
| { "CLD", AM_IMP }, // D8 | |
| { "CMP", AM_ABY }, // D9 | |
| { "NOP", AM_IMP }, // DA (illegal) | |
| { "DCP", AM_ABY }, // DB (illegal) | |
| { "TOP", AM_ABX }, // DC (illegal) | |
| { "CMP", AM_ABX }, // DD | |
| { "DEC", AM_ABX }, // DE | |
| { "DCP", AM_ABX }, // DF (illegal) | |
| { "CPX", AM_IMM }, // E0 | |
| { "SBC", AM_ZIX }, // E1 | |
| { "DOP", AM_IMM }, // E2 (illegal) | |
| { "ISC", AM_ZIX }, // E3 (illegal) | |
| { "CPX", AM_ZP }, // E4 | |
| { "SBC", AM_ZP }, // E5 | |
| { "INC", AM_ZP }, // E6 | |
| { "ISC", AM_ZP }, // E7 (illegal) | |
| { "INX", AM_IMP }, // E8 | |
| { "SBC", AM_IMM }, // E9 | |
| { "NOP", AM_IMP }, // EA | |
| { "SBC", AM_IMM }, // EB (illegal) | |
| { "CPX", AM_ABS }, // EC | |
| { "SBC", AM_ABS }, // ED | |
| { "INC", AM_ABS }, // EE | |
| { "ISC", AM_ABS }, // EF (illegal) | |
| { "BEQ", AM_REL }, // F0 | |
| { "SBC", AM_ZIY }, // F1 | |
| { "JAM", AM_IMP }, // F2 (illegal) | |
| { "ISC", AM_ZIY }, // F3 (illegal) | |
| { "DOP", AM_ZPX }, // F4 (illegal) | |
| { "SBC", AM_ZPX }, // F5 | |
| { "INC", AM_ZPX }, // F6 | |
| { "ISC", AM_ZPX }, // F7 (illegal) | |
| { "SED", AM_IMP }, // F8 | |
| { "SBC", AM_ABY }, // F9 | |
| { "NOP", AM_IMP }, // FA (illegal) | |
| { "ISC", AM_ABY }, // FB (illegal) | |
| { "TOP", AM_ABX }, // FC (illegal) | |
| { "SBC", AM_ABX }, // FD | |
| { "INC", AM_ABX }, // FE | |
| { "ISC", AM_ABX } };// FF (illegal) | |
| SDL_bool isws( char c ) | |
| { | |
| if( ( c == 9 ) || ( c == 32 ) ) return SDL_TRUE; | |
| return SDL_FALSE; | |
| } | |
| SDL_bool isbin( char c ) | |
| { | |
| if( ( c >= '0' ) && ( c <= '1' ) ) return SDL_TRUE; | |
| return SDL_FALSE; | |
| } | |
| SDL_bool isnum( char c ) | |
| { | |
| if( ( c >= '0' ) && ( c <= '9' ) ) return SDL_TRUE; | |
| return SDL_FALSE; | |
| } | |
| SDL_bool ishex( char c ) | |
| { | |
| if( isnum( c ) ) return SDL_TRUE; | |
| if( ( c >= 'a' ) && ( c <= 'f' ) ) return SDL_TRUE; | |
| if( ( c >= 'A' ) && ( c <= 'F' ) ) return SDL_TRUE; | |
| return SDL_FALSE; | |
| } | |
| SDL_bool isalph( char c ) | |
| { | |
| if( ( c >= 'a' ) && ( c <= 'z' ) ) return SDL_TRUE; | |
| if( ( c >= 'A' ) && ( c <= 'Z' ) ) return SDL_TRUE; | |
| return SDL_FALSE; | |
| } | |
| SDL_bool issymstart( char c ) | |
| { | |
| if( isalph( c ) ) return SDL_TRUE; | |
| if( c == '_' ) return SDL_TRUE; | |
| return SDL_FALSE; | |
| } | |
| SDL_bool issymchar( char c ) | |
| { | |
| if( issymstart( c ) ) return SDL_TRUE; | |
| if( isnum( c ) ) return SDL_TRUE; | |
| return SDL_FALSE; | |
| } | |
| int hexit( char c ) | |
| { | |
| if( isnum( c ) ) return c-'0'; | |
| if( ( c >= 'a' ) && ( c <= 'f' ) ) return c-('a'-10); | |
| if( ( c >= 'A' ) && ( c <= 'F' ) ) return c-('A'-10); | |
| return -1; | |
| } | |
| static int bp_at( struct machine *oric, unsigned short addr, int *xbp, int *mbp ) | |
| { | |
| int bpmask = 0, i; | |
| if( xbp ) *xbp = -1; | |
| if( mbp ) *mbp = -1; | |
| oric->cpu.anybp = SDL_FALSE; | |
| for( i=0; i<16; i++ ) | |
| { | |
| if( oric->cpu.breakpoints[i] != -1 ) | |
| { | |
| oric->cpu.anybp = SDL_TRUE; | |
| if( addr == oric->cpu.breakpoints[i] ) | |
| { | |
| bpmask |= 8; | |
| if( xbp ) *xbp = i; | |
| break; | |
| } | |
| } | |
| } | |
| oric->cpu.anymbp = SDL_FALSE; | |
| for( i=0; i<16; i++ ) | |
| { | |
| if( oric->cpu.membreakpoints[i].flags ) | |
| { | |
| oric->cpu.anymbp = SDL_TRUE; | |
| if( oric->cpu.membreakpoints[i].addr == addr ) | |
| { | |
| bpmask |= oric->cpu.membreakpoints[i].flags; | |
| if( mbp ) *mbp = i; | |
| break; | |
| } | |
| } | |
| } | |
| return bpmask; | |
| } | |
| // Don't mess with registers that change because you read them! | |
| unsigned char mon_read( struct machine *oric, unsigned short addr ) | |
| { | |
| // microdisc registers could screw things up | |
| if( oric->drivetype == DRV_MICRODISC ) | |
| { | |
| switch( addr ) | |
| { | |
| case 0x310: | |
| return oric->wddisk.r_status; | |
| case 0x311: | |
| return oric->wddisk.r_track; | |
| case 0x312: | |
| return oric->wddisk.r_sector; | |
| case 0x313: | |
| return oric->wddisk.r_data; | |
| case 0x314: | |
| return oric->md.intrq|0x7f; | |
| case 0x318: | |
| return oric->md.drq|0x7f; | |
| } | |
| } | |
| if( oric->drivetype == DRV_PRAVETZ ) | |
| { | |
| if ( ( 0x300 <= addr ) && ( addr <= 0x30f ) ) | |
| { | |
| return via_mon_read( &oric->via, addr ); | |
| } | |
| if ( ( 0x310 <= addr ) && ( addr <= 0x31f ) ) | |
| { | |
| return 0xFF; | |
| } | |
| return oric->cpu.read( &oric->cpu, addr ); | |
| } | |
| if( ( addr & 0xff00 ) == 0x0300 ) | |
| { | |
| if ( ( !oric->lightpen ) || ( addr < 0x3e0 ) || ( addr > 0x3e1 ) ) | |
| { | |
| return via_mon_read( &oric->via, addr ); | |
| } | |
| } | |
| return oric->cpu.read( &oric->cpu, addr ); | |
| } | |
| void mon_store_state( struct machine *oric ) | |
| { | |
| int k; | |
| for( k=0; k<65536; k++ ) | |
| { | |
| if( isram( oric, k ) ) | |
| mwatch_old[k] = mon_read( oric, k ); | |
| } | |
| mwatch_oldvalid = SDL_TRUE; | |
| cpu_old = oric->cpu; | |
| vidraster_old = oric->vid_raster; | |
| frames_old = oric->frames; | |
| cpu_oldvalid = SDL_TRUE; | |
| ay_old = oric->ay; | |
| ay_oldvalid = SDL_TRUE; | |
| via_old = oric->via; | |
| via_oldvalid = SDL_TRUE; | |
| via2_old = oric->tele_via; | |
| via2_oldvalid = SDL_TRUE; | |
| } | |
| void mon_set_modified( struct machine *oric ) | |
| { | |
| if( modified ) return; | |
| modified = SDL_TRUE; | |
| mon_store_state( oric ); | |
| } | |
| void dbg_scroll( void ) | |
| { | |
| int x, y, s, d; | |
| struct textzone *ptz = tz[TZ_DEBUG]; | |
| s = ptz->w*2+1; | |
| d = ptz->w+1; | |
| for( y=0; y<18; y++ ) | |
| { | |
| for( x=0; x<48; x++ ) | |
| { | |
| ptz->tx[d] = ptz->tx[s]; | |
| ptz->fc[d] = ptz->fc[s]; | |
| ptz->bc[d++] = ptz->bc[s++]; | |
| } | |
| d += 2; | |
| s += 2; | |
| } | |
| for( x=0; x<48; x++ ) | |
| { | |
| ptz->tx[d] = ' '; | |
| ptz->fc[d] = 2; | |
| ptz->bc[d++] = 3; | |
| } | |
| } | |
| void dbg_printf( char *fmt, ... ) | |
| { | |
| va_list ap; | |
| dbg_scroll(); | |
| va_start( ap, fmt ); | |
| if( vsnprintf( vsptmp, VSPTMPSIZE, fmt, ap ) != -1 ) | |
| { | |
| vsptmp[VSPTMPSIZE-1] = 0; | |
| #if LOG_DEBUG | |
| if( debug_logfile ) | |
| { | |
| fprintf( debug_logfile, "%s\n", vsptmp ); | |
| fflush( debug_logfile ); | |
| } | |
| #endif | |
| vsptmp[48] = 0; | |
| tzstrpos( tz[TZ_DEBUG], 1, 19, vsptmp ); | |
| } | |
| va_end( ap ); | |
| } | |
| struct msym *mon_tab_find_sym_by_addr( struct symboltable *stab, struct machine *oric, unsigned short addr, SDL_bool *override_romdis ) | |
| { | |
| int i, j, k; | |
| SDL_bool romdis; | |
| romdis = oric->romdis; | |
| if( ( oric->drivetype == DRV_JASMIN ) && ( oric->jasmin.olay ) ) | |
| romdis = SDL_FALSE; | |
| if (override_romdis) | |
| romdis = *override_romdis; | |
| for( i=0; i<stab->numsyms; i++ ) | |
| { | |
| if( oric->type == MACH_TELESTRAT ) | |
| { | |
| if( stab->syms[i].addr >= 0xc000 ) | |
| { | |
| for( j=0, k=SYMF_TELEBANK0; j<8; j++, k<<=1 ) | |
| { | |
| if( ((stab->syms[i].flags&k)==0) && ( oric->tele_currbank == j ) ) | |
| break; | |
| } | |
| if( j != 8 ) continue; | |
| } | |
| } else { | |
| if( stab->syms[i].flags&SYMF_MICRODISC ) | |
| { | |
| if( ( oric->drivetype != DRV_MICRODISC ) || ( !oric->md.diskrom ) ) | |
| continue; | |
| } | |
| if( (stab->syms[i].flags&SYMF_JASMIN) && ( oric->drivetype != DRV_JASMIN ) ) | |
| continue; | |
| if( romdis ) | |
| { | |
| if( (stab->syms[i].flags&SYMF_ROMDIS0) != 0 ) | |
| continue; | |
| } else { | |
| if( (stab->syms[i].flags&SYMF_ROMDIS1) != 0 ) | |
| continue; | |
| } | |
| } | |
| if( addr == stab->syms[i].addr ) | |
| return &stab->syms[i]; | |
| } | |
| return NULL; | |
| } | |
| struct msym *mon_tab_find_sym_by_name( struct symboltable *stab, struct machine *oric, char *name, int *symnum ) | |
| { | |
| int i, j, k, romdis; | |
| romdis = oric->romdis; | |
| if( ( oric->drivetype == DRV_JASMIN ) && ( oric->jasmin.olay ) ) | |
| romdis = 1; | |
| for( i=0; i<stab->numsyms; i++ ) | |
| { | |
| if( oric->type == MACH_TELESTRAT ) | |
| { | |
| if( stab->syms[i].addr >= 0xc000 ) | |
| { | |
| for( j=0, k=SYMF_TELEBANK0; j<8; j++, k<<=1 ) | |
| { | |
| if( ((stab->syms[i].flags&k)==0) && ( oric->tele_currbank == j ) ) | |
| break; | |
| } | |
| if( j != 8 ) continue; | |
| } | |
| } else { | |
| if( stab->syms[i].flags&SYMF_MICRODISC ) | |
| { | |
| if( ( oric->drivetype != DRV_MICRODISC ) || ( !oric->md.diskrom ) ) | |
| continue; | |
| } | |
| if( (stab->syms[i].flags&SYMF_JASMIN) && ( oric->drivetype != DRV_JASMIN ) ) | |
| continue; | |
| if( romdis ) | |
| { | |
| if( (stab->syms[i].flags&SYMF_ROMDIS0) != 0 ) | |
| continue; | |
| } else { | |
| if( (stab->syms[i].flags&SYMF_ROMDIS1) != 0 ) | |
| continue; | |
| } | |
| } | |
| if( !oric->symbolscase ) | |
| { | |
| if( strcasecmp( name, stab->syms[i].name ) == 0 ) | |
| { | |
| if( symnum ) (*symnum) = i; | |
| return &stab->syms[i]; | |
| } | |
| } else { | |
| if( strcmp( name, stab->syms[i].name ) == 0 ) | |
| { | |
| if( symnum ) (*symnum) = i; | |
| return &stab->syms[i]; | |
| } | |
| } | |
| } | |
| if( symnum ) (*symnum) = -1; | |
| return NULL; | |
| } | |
| struct msym *mon_find_sym_by_addr( struct machine *oric, unsigned short addr, SDL_bool *override_romdis ) | |
| { | |
| struct msym *ret; | |
| ret = mon_tab_find_sym_by_addr( &oric->usersyms, oric, addr, override_romdis ); | |
| if( !ret ) ret = mon_tab_find_sym_by_addr( &oric->romsyms, oric, addr, override_romdis ); | |
| if( ( !ret ) && ( oric->type == MACH_TELESTRAT ) ) ret = mon_tab_find_sym_by_addr( &oric->tele_banksyms[oric->tele_currbank], oric, addr, override_romdis ); | |
| if( ( !ret ) && ( oric->disksyms ) ) ret = mon_tab_find_sym_by_addr( oric->disksyms, oric, addr, override_romdis ); | |
| if( ret ) return ret; | |
| return mon_tab_find_sym_by_addr( &defaultsyms, oric, addr, override_romdis ); | |
| } | |
| struct msym *mon_find_sym_by_name( struct machine *oric, char *name ) | |
| { | |
| struct msym *ret; | |
| ret = mon_tab_find_sym_by_name( &oric->usersyms, oric, name, NULL ); | |
| if( !ret ) ret = mon_tab_find_sym_by_name( &oric->romsyms, oric, name, NULL ); | |
| if( ( !ret ) && ( oric->type == MACH_TELESTRAT ) ) ret = mon_tab_find_sym_by_name( &oric->tele_banksyms[oric->tele_currbank], oric, name, NULL ); | |
| if( ( !ret ) && ( oric->disksyms ) ) ret = mon_tab_find_sym_by_name( oric->disksyms, oric, name, NULL ); | |
| if( ret ) return ret; | |
| return mon_tab_find_sym_by_name( &defaultsyms, oric, name, NULL ); | |
| } | |
| SDL_bool mon_addsym( struct symboltable *stab, unsigned short addr, unsigned short flags, char *name, struct msym **symptr ) | |
| { | |
| int i; | |
| if( symptr ) (*symptr) = NULL; | |
| // Is it a dynamic symbol table? | |
| if( stab->symspace == -1 ) return SDL_FALSE; | |
| if( ( !stab->syms ) || ( stab->symspace < (stab->numsyms+1) ) ) | |
| { | |
| struct msym *newbuf; | |
| newbuf = malloc( sizeof( struct msym ) * (stab->symspace+64) ); | |
| if( !newbuf ) return SDL_FALSE; | |
| if( ( stab->syms ) && ( stab->numsyms > 0 ) ) | |
| memcpy( newbuf, stab->syms, sizeof( struct msym ) * stab->numsyms ); | |
| free( stab->syms ); | |
| stab->syms = newbuf; | |
| stab->symspace += 64; | |
| for( i=stab->numsyms; i<stab->symspace; i++ ) | |
| stab->syms[i].name = NULL; | |
| } | |
| if( !stab->syms[stab->numsyms].name ) | |
| { | |
| stab->syms[stab->numsyms].name = malloc( 128 ); | |
| if( !stab->syms[stab->numsyms].name ) return SDL_FALSE; | |
| } | |
| stab->syms[stab->numsyms].addr = addr; | |
| stab->syms[stab->numsyms].flags = flags; | |
| strncpy( stab->syms[stab->numsyms].name, name, 128 ); | |
| stab->syms[stab->numsyms].name[127] = 0; | |
| if( strlen( name ) > SNAME_LEN ) | |
| { | |
| strncpy( stab->syms[stab->numsyms].sname, name, (SNAME_LEN-1) ); | |
| stab->syms[stab->numsyms].sname[SNAME_LEN-1] = 22; | |
| stab->syms[stab->numsyms].sname[SNAME_LEN] = 0; | |
| } else { | |
| strcpy( stab->syms[stab->numsyms].sname, name ); | |
| } | |
| if( strlen( name ) > SSNAME_LEN ) | |
| { | |
| strncpy( stab->syms[stab->numsyms].ssname, name, (SSNAME_LEN-1) ); | |
| stab->syms[stab->numsyms].ssname[SSNAME_LEN-1] = 22; | |
| stab->syms[stab->numsyms].ssname[SSNAME_LEN] = 0; | |
| } else { | |
| strcpy( stab->syms[stab->numsyms].ssname, name ); | |
| } | |
| if( symptr ) *(symptr) = &stab->syms[stab->numsyms]; | |
| stab->numsyms++; | |
| return SDL_TRUE; | |
| } | |
| void mon_init_symtab( struct symboltable *stab ) | |
| { | |
| stab->syms = NULL; | |
| stab->numsyms = 0; | |
| stab->symspace = 0; | |
| } | |
| void mon_freesyms( struct symboltable *stab ) | |
| { | |
| // Is it a dynamic table? | |
| if( stab->symspace == -1 ) return; | |
| if (stab->syms) | |
| { | |
| int i; | |
| for (i = 0; i < stab->numsyms; i++) | |
| { | |
| free(stab->syms[i].name); | |
| } | |
| free(stab->syms); | |
| } | |
| stab->syms = NULL; | |
| stab->numsyms = 0; | |
| stab->symspace = 0; | |
| } | |
| char *mon_disassemble( struct machine *oric, unsigned short *paddr, SDL_bool *looped, SDL_bool filemode ) | |
| { | |
| unsigned short iaddr, addr; | |
| unsigned char op, a1, a2; | |
| int i; | |
| char *tmpsname, *disptr; | |
| char sname[SNAME_LEN+1]; | |
| struct msym *csym; | |
| disptr = distmp; | |
| iaddr = *paddr; | |
| if( looped ) *looped = SDL_FALSE; | |
| tmpsname = ""; | |
| if( !filemode ) | |
| { | |
| csym = mon_find_sym_by_addr( oric, iaddr, NULL ); | |
| if( csym ) tmpsname = csym->sname; | |
| } else { | |
| csym = mon_find_sym_by_addr( oric, iaddr, NULL ); | |
| if( csym ) | |
| { | |
| tmpsname = csym->name; | |
| if( strlen( tmpsname ) > SNAME_LEN ) | |
| { | |
| int ln = strlen(tmpsname); | |
| ln = (ln<127)? ln : 126; | |
| memcpy( distmp, tmpsname, ln ); | |
| distmp[ln] = '\n'; | |
| distmp[ln+1] = 0; | |
| disptr = &distmp[strlen(distmp)]; | |
| tmpsname = ""; | |
| } | |
| } | |
| } | |
| strcpy( sname, tmpsname ); | |
| for( i=(int)strlen(sname); i<SNAME_LEN; i++ ) | |
| sname[i] = 32; | |
| sname[i] = 0; | |
| op = mon_read( oric, (*paddr)++ ); | |
| switch( distab[op].amode ) | |
| { | |
| case AM_IMP: | |
| sprintf( disptr, "%s %04X %02X %s", sname, iaddr, op, distab[op].name ); | |
| break; | |
| case AM_IMM: | |
| a1 = mon_read( oric, (*paddr)++ ); | |
| sprintf( disptr, "%s %04X %02X %02X %s #$%02X", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| break; | |
| case AM_ZP: | |
| case AM_ZPX: | |
| case AM_ZPY: | |
| a1 = mon_read( oric, (*paddr)++ ); | |
| csym = mon_find_sym_by_addr( oric, a1, NULL ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s %s", sname, iaddr, op, a1, distab[op].name, filemode ? csym->name : csym->sname ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s $%02X", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| if( distab[op].amode == AM_ZP ) break; | |
| strcat( disptr, distab[op].amode == AM_ZPX ? ",X" : ",Y" ); | |
| break; | |
| case AM_ABS: | |
| case AM_ABX: | |
| case AM_ABY: | |
| a1 = mon_read( oric, (*paddr)++ ); | |
| a2 = mon_read( oric, (*paddr)++ ); | |
| csym = mon_find_sym_by_addr( oric, (a2<<8)|a1, NULL ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s %s", sname, iaddr, op, a1, a2, distab[op].name, filemode ? csym->name : csym->sname ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s $%02X%02X", sname, iaddr, op, a1, a2, distab[op].name, a2, a1 ); | |
| if( distab[op].amode == AM_ABS ) break; | |
| strcat( disptr, distab[op].amode == AM_ABX ? ",X" : ",Y" ); | |
| break; | |
| case AM_ZIX: | |
| a1 = mon_read( oric, (*paddr)++ ); | |
| csym = mon_find_sym_by_addr( oric, a1, NULL ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s (%s,X)", sname, iaddr, op, a1, distab[op].name, filemode ? csym->name : csym->ssname ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s ($%02X,X)", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| break; | |
| case AM_ZIY: | |
| a1 = mon_read( oric, (*paddr)++ ); | |
| csym = mon_find_sym_by_addr( oric, a1, NULL ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s (%s),Y", sname, iaddr, op, a1, distab[op].name, filemode ? csym->name : csym->ssname ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s ($%02X),Y", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| break; | |
| case AM_REL: | |
| a1 = mon_read( oric, (*paddr)++ ); | |
| addr = ((*paddr)+((signed char)a1))&0xffff; | |
| csym = mon_find_sym_by_addr( oric, addr, NULL ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s %s", sname, iaddr, op, a1, distab[op].name, filemode ? csym->name : csym->sname ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s $%04X", sname, iaddr, op, a1, distab[op].name, addr ); | |
| break; | |
| case AM_IND: | |
| a1 = mon_read( oric, (*paddr)++ ); | |
| a2 = mon_read( oric, (*paddr)++ ); | |
| csym = mon_find_sym_by_addr( oric, (a2<<8)|a1, NULL ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s (%s)", sname, iaddr, op, a1, a2, distab[op].name, filemode ? csym->name : csym->sname ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s ($%02X%02X)", sname, iaddr, op, a1, a2, distab[op].name, a2, a1 ); | |
| break; | |
| default: | |
| strcpy( disptr, " WTF?" ); | |
| break; | |
| } | |
| for( i=(int)strlen(disptr); i<47; i++ ) | |
| disptr[i] = 32; | |
| disptr[i] = 0; | |
| switch( bp_at( oric, iaddr, NULL, NULL ) ) | |
| { | |
| case ( MBPF_READ): disptr[SNAME_LEN+1] = 'r'; break; | |
| case ( MBPF_WRITE ): disptr[SNAME_LEN+1] = 'w'; break; | |
| case ( MBPF_WRITE|MBPF_READ): disptr[SNAME_LEN+1] = 'a'; break; | |
| case ( MBPF_CHANGE ): disptr[SNAME_LEN+1] = 'c'; break; | |
| case ( MBPF_CHANGE |MBPF_READ): disptr[SNAME_LEN+1] = 'g'; break; | |
| case ( MBPF_CHANGE|MBPF_WRITE ): disptr[SNAME_LEN+1] = 'm'; break; | |
| case ( MBPF_CHANGE|MBPF_WRITE|MBPF_READ): disptr[SNAME_LEN+1] = '+'; break; | |
| case (8 ): disptr[SNAME_LEN+1] = 'X'; break; | |
| case (8| MBPF_READ): disptr[SNAME_LEN+1] = 'R'; break; | |
| case (8| MBPF_WRITE ): disptr[SNAME_LEN+1] = 'W'; break; | |
| case (8| MBPF_WRITE|MBPF_READ): disptr[SNAME_LEN+1] = 'A'; break; | |
| case (8|MBPF_CHANGE ): disptr[SNAME_LEN+1] = 'C'; break; | |
| case (8|MBPF_CHANGE |MBPF_READ): disptr[SNAME_LEN+1] = 'G'; break; | |
| case (8|MBPF_CHANGE|MBPF_WRITE ): disptr[SNAME_LEN+1] = 'M'; break; | |
| case (8|MBPF_CHANGE|MBPF_WRITE|MBPF_READ): disptr[SNAME_LEN+1] = '*'; break; | |
| } | |
| if( iaddr == oric->cpu.pc ) | |
| disptr[SNAME_LEN+2] = '>'; | |
| if( ( looped ) && ( iaddr > *paddr ) ) | |
| *looped = SDL_TRUE; | |
| return distmp; | |
| } | |
| static void mon_regmod( int x, int y, int w ) | |
| { | |
| int offs, i; | |
| offs = y*tz[TZ_REGS]->w+x; | |
| for( i=0; i<w; i++, offs++ ) | |
| { | |
| tz[TZ_REGS]->fc[offs] = 1; | |
| tz[TZ_REGS]->bc[offs] = 8; | |
| } | |
| } | |
| void mon_update_regs( struct machine *oric ) | |
| { | |
| int i; | |
| unsigned short addr, pc; | |
| struct msym *csym; | |
| char stmp[48]; | |
| pc = oric->cpu.pc; | |
| if( ( oric->cpu.irq ) && ( oric->cpu.f_i == 0 ) ) | |
| pc = (mon_read( oric, 0xffff )<<8) | mon_read( oric, 0xfffe ); | |
| tzprintfpos( tz[TZ_REGS], 2, 2, "PC=%04X SP=01%02X A=%02X X=%02X Y=%02X LPC=%04X", | |
| pc, | |
| oric->cpu.sp, | |
| oric->cpu.a, | |
| oric->cpu.x, | |
| oric->cpu.y, | |
| oric->cpu.lastpc ); | |
| csym = mon_find_sym_by_addr( oric, pc, NULL ); | |
| if( csym ) | |
| { | |
| if( strlen( csym->name ) > 46 ) | |
| { | |
| strncpy( stmp, csym->name, 46 ); | |
| stmp[46] = 0; | |
| } else { | |
| strcpy( stmp, csym->name ); | |
| } | |
| tzstrpos( tz[TZ_REGS], 2, 3, stmp ); | |
| } else { | |
| tzprintfpos( tz[TZ_REGS], 2, 3, "%46s", " " ); | |
| } | |
| tzprintfpos( tz[TZ_REGS], 2, 4, "CY=%09d", oric->cpu.cycles ); | |
| tzprintfpos( tz[TZ_REGS], 2, 5, "FM=%06d RS=%03d", oric->frames, oric->vid_raster ); | |
| tzstrpos( tz[TZ_REGS], 35, 4, (oric->cpu.irq&IRQF_VIA) ? "VIA" : " " ); | |
| tzstrpos( tz[TZ_REGS], 35, 5, (oric->cpu.irq&IRQF_DISK) ? "DISK" : " " ); | |
| tzstrpos( tz[TZ_REGS], 20, 4, "NV-BDIZC" ); | |
| tzprintfpos( tz[TZ_REGS], 20, 5, "%01X%01X1%01X%01X%01X%01X%01X", | |
| oric->cpu.f_n, | |
| oric->cpu.f_v, | |
| oric->cpu.f_b, | |
| oric->cpu.f_d, | |
| oric->cpu.f_i, | |
| oric->cpu.f_z, | |
| oric->cpu.f_c ); | |
| tzprintfpos( tz[TZ_REGS], 30, 4, "NMI=%04X RST=%04X", | |
| (oric->cpu.read( &oric->cpu, 0xfffb )<<8)|oric->cpu.read( &oric->cpu, 0xfffa ), | |
| (oric->cpu.read( &oric->cpu, 0xfffd )<<8)|oric->cpu.read( &oric->cpu, 0xfffc ) ); | |
| tzprintfpos( tz[TZ_REGS], 30, 5, "IRQ=%04X", (oric->cpu.read( &oric->cpu, 0xffff )<<8)|oric->cpu.read( &oric->cpu, 0xfffe ) ); | |
| addr = pc; | |
| for( i=0; i<10; i++ ) | |
| { | |
| disaddrs[i] = addr; | |
| tzsetcol( tz[TZ_REGS], (addr==pc) ? 1 : 2, 3 ); | |
| tzstrpos( tz[TZ_REGS], 23, 7+i, " " ); | |
| tzstrpos( tz[TZ_REGS], 2, 7+i, mon_disassemble( oric, &addr, NULL, SDL_FALSE ) ); | |
| } | |
| if( cpu_oldvalid ) | |
| { | |
| if( cpu_old.pc != pc ) mon_regmod( 5, 2, 4 ); | |
| if( cpu_old.sp != oric->cpu.sp ) mon_regmod( 14, 2, 4 ); | |
| if( cpu_old.a != oric->cpu.a ) mon_regmod( 22, 2, 2 ); | |
| if( cpu_old.x != oric->cpu.x ) mon_regmod( 28, 2, 2 ); | |
| if( cpu_old.y != oric->cpu.y ) mon_regmod( 34, 2, 2 ); | |
| if( cpu_old.cycles != oric->cpu.cycles ) mon_regmod( 5, 4, 9 ); | |
| if( frames_old != oric->frames ) mon_regmod( 5, 5, 6 ); | |
| if( vidraster_old != oric->vid_raster ) mon_regmod( 15, 5, 3 ); | |
| if( cpu_old.f_n != oric->cpu.f_n ) mon_regmod( 20, 5, 1 ); | |
| if( cpu_old.f_v != oric->cpu.f_v ) mon_regmod( 21, 5, 1 ); | |
| if( cpu_old.f_b != oric->cpu.f_b ) mon_regmod( 23, 5, 1 ); | |
| if( cpu_old.f_d != oric->cpu.f_d ) mon_regmod( 24, 5, 1 ); | |
| if( cpu_old.f_i != oric->cpu.f_i ) mon_regmod( 25, 5, 1 ); | |
| if( cpu_old.f_z != oric->cpu.f_z ) mon_regmod( 26, 5, 1 ); | |
| if( cpu_old.f_c != oric->cpu.f_c ) mon_regmod( 27, 5, 1 ); | |
| if( (cpu_old.irq&IRQF_VIA) != (oric->cpu.irq&IRQF_VIA) ) mon_regmod( 35, 4, 3 ); | |
| if( (cpu_old.irq&IRQF_DISK) != (oric->cpu.irq&IRQF_DISK) ) mon_regmod( 35, 5, 4 ); | |
| } | |
| } | |
| static void mon_click_regs( struct machine *oric, SDL_bool *needrender, int x, int y, SDL_bool dblclk ) | |
| { | |
| char cmdtmp[32]; | |
| if( ( dblclk ) && ( y == 5 ) ) | |
| { | |
| switch( x ) | |
| { | |
| case 20: mon_set_modified( oric ); oric->cpu.f_n ^= 1; *needrender = SDL_TRUE; return; | |
| case 21: mon_set_modified( oric ); oric->cpu.f_v ^= 1; *needrender = SDL_TRUE; return; | |
| case 23: mon_set_modified( oric ); oric->cpu.f_b ^= 1; *needrender = SDL_TRUE; return; | |
| case 24: mon_set_modified( oric ); oric->cpu.f_d ^= 1; *needrender = SDL_TRUE; return; | |
| case 25: mon_set_modified( oric ); oric->cpu.f_i ^= 1; *needrender = SDL_TRUE; return; | |
| case 26: mon_set_modified( oric ); oric->cpu.f_z ^= 1; *needrender = SDL_TRUE; return; | |
| case 27: mon_set_modified( oric ); oric->cpu.f_c ^= 1; *needrender = SDL_TRUE; return; | |
| } | |
| } | |
| if( ( dblclk ) && ( y >= 7 ) && ( y < 17 ) ) | |
| { | |
| int i; | |
| if( bp_at( oric, disaddrs[y-7], &i, NULL ) & 8 ) | |
| { | |
| sprintf( cmdtmp, "bc %d", i ); | |
| mon_do_cmd( cmdtmp, oric, needrender ); | |
| *needrender = SDL_TRUE; | |
| } else { | |
| sprintf( cmdtmp, "bs $%04x", disaddrs[y-7] ); | |
| mon_do_cmd( cmdtmp, oric, needrender ); | |
| *needrender = SDL_TRUE; | |
| } | |
| return; | |
| } | |
| } | |
| static void mon_viamod( int x, int y, int w, struct textzone *vtz ) | |
| { | |
| int offs, i; | |
| offs = y*vtz->w+x; | |
| for( i=0; i<w; i++, offs++ ) | |
| { | |
| vtz->fc[offs] = 1; | |
| vtz->bc[offs] = 8; | |
| } | |
| } | |
| void mon_update_via( struct machine *oric, struct textzone *vtz, struct via *v, struct via *old, SDL_bool *oldvalid ) | |
| { | |
| int i, j, o; | |
| unsigned char val; | |
| char *names[] = { "IORB ", "IORAh", "DDRB ", "DDRA ", "T1CL ", "T1CH ", "T1LL ", "T1LH ", "T2CL ", "T2CH ", "SR ", "ACR ", "PCR ", "IFR ", "IER ", "IORA " }; | |
| for( i=0; i<16; i++ ) | |
| { | |
| val = via_mon_read( v, v == &oric->via ? 0x300+i : 0x320+i ); | |
| tzprintfpos( vtz, 2, i+1, "%04X: %s $%02X %%", (v == &oric->via) ? 0x300+i : 0x320+i, names[i], val ); | |
| for( j=128; j; j>>=1 ) | |
| tzputc(vtz, (val&j)?'1':'0'); | |
| if( *oldvalid ) | |
| { | |
| unsigned char oval = via_mon_read(old, (v == &oric->via) ? 0x300+i : 0x320+i ); | |
| if( val != oval ) mon_viamod( 16, i+1, 2, vtz ); | |
| for( j=128, o=19; j; j>>=1, o++ ) | |
| { | |
| if ((val&j) != (oval&j)) | |
| mon_viamod( o, i+1, 1, vtz ); | |
| } | |
| } | |
| } | |
| tzprintfpos( vtz, 2, 18, "---------- TAPE ----------"); | |
| tzprintfpos( vtz, 2, 19, "OFS %08u LEN %08u", oric->tapeoffs, oric->tapelen ); | |
| /* | |
| if( v == &oric->via ) | |
| { | |
| tzprintfpos( vtz, 2, 11, "TAPE OFFS = %07d", oric->tapeoffs ); | |
| tzprintfpos( vtz, 2, 12, "TAPE LEN = %07d", oric->tapelen ); | |
| tzprintfpos( vtz, 2, 13, "COUNT = %07d", oric->tapecount ); | |
| tzprintfpos( vtz, 2, 14, "BIT = %02X DATA = %1X", | |
| oric->tapebit, | |
| oric->tapetime == TAPE_1_PULSE ); | |
| tzprintfpos( vtz, 2, 15, "MOTOR = %1X", oric->tapemotor ); | |
| } | |
| if( v == &oric->tele_via ) | |
| { | |
| tzprintfpos( vtz, 2, 11, "BANK = %02X", oric->tele_currbank ); | |
| } | |
| if( *oldvalid ) | |
| { | |
| if( old->pcr != v->pcr ) mon_viamod( 6, 2, 2, vtz ); | |
| if( old->acr != v->acr ) mon_viamod( 13, 2, 2, vtz ); | |
| if( old->sr != v->sr ) mon_viamod( 19, 2, 2, vtz ); | |
| if( old->ifr != v->ifr ) mon_viamod( 6, 3, 2, vtz ); | |
| if( old->ier != v->ier ) mon_viamod( 13, 3, 2, vtz ); | |
| if( old->ddra != v->ddra ) mon_viamod( 12, 5, 2, vtz ); | |
| if( old->ddrb != v->ddrb ) mon_viamod( 18, 5, 2, vtz ); | |
| if( old->ca1 != v->ca1 ) mon_viamod( 6, 6, 1, vtz ); | |
| if( old->ca2 != v->ca2 ) mon_viamod( 12, 6, 1, vtz ); | |
| if( old->cb1 != v->cb1 ) mon_viamod( 20, 6, 1, vtz ); | |
| if( old->cb2 != v->cb2 ) mon_viamod( 26, 6, 1, vtz ); | |
| if( old->t1c != v->t1c ) mon_viamod( 15, 8, 4, vtz ); | |
| if( old->t2c != v->t2c ) mon_viamod( 15, 9, 4, vtz ); | |
| if( ((old->t1l_h<<8)|(old->t1l_l)) != ((v->t1l_h<<8)|(v->t1l_l)) ) mon_viamod( 6, 8, 4, vtz ); | |
| if( ((old->t2l_h<<8)|(old->t2l_l)) != ((v->t2l_h<<8)|(v->t2l_l)) ) mon_viamod( 6, 9, 4, vtz ); | |
| if( ((v->ora&v->ddra)|(v->ira&(~v->ddra))) != ((old->ora&old->ddra)|(old->ira&(~old->ddra))) ) mon_viamod( 4, 5, 2, vtz ); | |
| if( ((v->orb&v->ddrb)|(v->irb&(~v->ddrb))) != ((old->orb&old->ddrb)|(old->irb&(~old->ddrb))) ) mon_viamod( 26, 5, 2, vtz ); | |
| } | |
| */ | |
| } | |
| static void mon_aymod( int x, int y, int w ) | |
| { | |
| int offs, i; | |
| offs = y*tz[TZ_AY]->w+x; | |
| for( i=0; i<w; i++, offs++ ) | |
| { | |
| tz[TZ_AY]->fc[offs] = 1; | |
| tz[TZ_AY]->bc[offs] = 8; | |
| } | |
| } | |
| static void printayregbits( struct machine *oric, char *str, Sint16 x, Sint16 y, int reg, Uint8 bits ) | |
| { | |
| int i, o, fc, bc; | |
| Uint8 vnew, vold; | |
| struct textzone *ptz = tz[TZ_AY]; | |
| vnew = oric->ay.eregs[reg]; | |
| vold = ay_old.eregs[reg]; | |
| tzprintfpos( ptz, x, y, str, vnew ); | |
| fc = 2; | |
| bc = 3; | |
| if( ( ay_oldvalid ) && ( ay_old.eregs[reg] != oric->ay.eregs[reg] ) ) | |
| { | |
| fc = 1; | |
| bc = 8; | |
| mon_aymod( x+14, y, 2 ); | |
| } | |
| x+=18; | |
| o = (y*ptz->w)+x; | |
| bits = 8-bits; | |
| for( i=0; i<8; i++ ) | |
| { | |
| if( i >= bits ) | |
| ptz->tx[o] = (vnew&(0x80>>i)) ? '1' : '0'; | |
| else | |
| ptz->tx[o] = ' '; | |
| if( (vnew&(0x80)>>i) != (vold&(0x80)>>i) ) | |
| { | |
| ptz->fc[o] = fc; | |
| ptz->bc[o] = bc; | |
| } else { | |
| ptz->fc[o] = 2; | |
| ptz->bc[o] = 3; | |
| } | |
| o++; | |
| } | |
| } | |
| void mon_update_ay( struct machine *oric ) | |
| { | |
| char *strs[] = { "INACTIVE", | |
| "READ ", | |
| "WRITE ", | |
| "LATCH " }; | |
| tzprintfpos( tz[TZ_AY], 2, 1, "CTRL=%s REG=%02X", | |
| strs[oric->ay.bmode&3], | |
| oric->ay.creg ); | |
| if( ay_oldvalid ) | |
| { | |
| if( (ay_old.bmode&3) != (oric->ay.bmode&3) ) mon_aymod( 7, 1, 8 ); | |
| if( ay_old.creg != oric->ay.creg ) mon_aymod( 21, 1, 2 ); | |
| } | |
| printayregbits( oric, "R0 Pitch A L $%02X %%", 2, 2, AY_CHA_PER_L, 8 ); | |
| printayregbits( oric, "R1 Pitch A H $%02X %%", 2, 3, AY_CHA_PER_H, 4 ); | |
| printayregbits( oric, "R2 Pitch B L $%02X %%", 2, 4, AY_CHB_PER_L, 8 ); | |
| printayregbits( oric, "R3 Pitch B H $%02X %%", 2, 5, AY_CHB_PER_H, 4 ); | |
| printayregbits( oric, "R4 Pitch C L $%02X %%", 2, 6, AY_CHC_PER_L, 8 ); | |
| printayregbits( oric, "R5 Pitch C H $%02X %%", 2, 7, AY_CHC_PER_H, 4 ); | |
| printayregbits( oric, "R6 Noise $%02X %%", 2, 9, AY_NOISE_PER, 5 ); | |
| printayregbits( oric, "R7 Status $%02X %%", 2,10, AY_STATUS, 7 ); | |
| printayregbits( oric, "R8 Volume A $%02X %%", 2,12, AY_CHA_AMP, 5 ); | |
| printayregbits( oric, "R9 Volume B $%02X %%", 2,13, AY_CHB_AMP, 5 ); | |
| printayregbits( oric, "RA Volume C $%02X %%", 2,14, AY_CHC_AMP, 5 ); | |
| printayregbits( oric, "RB Env Per L $%02X %%", 2,16, AY_ENV_PER_L, 8 ); | |
| printayregbits( oric, "RC Env Per H $%02X %%", 2,17, AY_ENV_PER_H, 8 ); | |
| printayregbits( oric, "RD Env Cycle $%02X %%", 2,18, AY_ENV_CYCLE, 4 ); | |
| printayregbits( oric, "RE Key Col $%02X %%", 2,19, AY_PORT_A, 8 ); | |
| /* | |
| tzprintfpos( tz[TZ_AY], 2, 4, "A:P=%04X A=%02X N:PER=%02X", | |
| (oric->ay.regs[AY_CHA_PER_H]<<8)|(oric->ay.regs[AY_CHA_PER_L]), | |
| oric->ay.regs[AY_CHA_AMP], | |
| oric->ay.regs[AY_NOISE_PER] ); | |
| tzprintfpos( tz[TZ_AY], 2, 5, "B:P=%04X A=%02X E:PER=%04X", | |
| (oric->ay.regs[AY_CHB_PER_H]<<8)|(oric->ay.regs[AY_CHB_PER_L]), | |
| oric->ay.regs[AY_CHB_AMP], | |
| (oric->ay.regs[AY_ENV_PER_H]<<8)|(oric->ay.regs[AY_ENV_PER_L]) ); | |
| tzprintfpos( tz[TZ_AY], 2, 6, "C:P=%04X A=%02X E:CYC=%02X", | |
| (oric->ay.regs[AY_CHC_PER_H]<<8)|(oric->ay.regs[AY_CHC_PER_L]), | |
| oric->ay.regs[AY_CHC_AMP], | |
| oric->ay.regs[AY_ENV_CYCLE] ); | |
| tzprintfpos( tz[TZ_AY], 2, 8, "STATUS=%02X", | |
| oric->ay.regs[AY_STATUS] ); | |
| tzprintfpos( tz[TZ_AY], 2, 9, "PORT=%02X", | |
| oric->ay.regs[AY_PORT_A] ); | |
| */ | |
| } | |
| /* | |
| Uint8 r_status; | |
| Uint8 cmd; | |
| Uint8 r_track; | |
| Uint8 r_sector; | |
| Uint8 r_data; | |
| Uint8 c_drive; | |
| Uint8 c_side; | |
| Uint8 c_track; | |
| SDL_bool last_step_in; | |
| void (*setintrq)(void *); | |
| void (*clrintrq)(void *); | |
| void *intrqarg; | |
| void (*setdrq)(void *); | |
| void (*clrdrq)(void *); | |
| void *drqarg; | |
| struct diskimage *disk[MAX_DRIVES]; | |
| int currentop; | |
| int delayedint; | |
| */ | |
| void mon_update_disk( struct machine *oric ) | |
| { | |
| char *opname; | |
| if( oric->drivetype == DRV_NONE ) | |
| return; | |
| if( oric->drivetype == DRV_PRAVETZ ) | |
| { | |
| int i = oric->wddisk.c_drive; | |
| tzprintfpos( tz[TZ_DISK], 2, 2, "DRIVE=%02X EXT=%04X", | |
| oric->wddisk.c_drive, | |
| oric->pravetz.extension ); | |
| tzprintfpos( tz[TZ_DISK], 2, 3, "VOL=%02X SEL=%02X", | |
| oric->pravetz.drv[i].volume, | |
| oric->pravetz.drv[i].select ); | |
| tzprintfpos( tz[TZ_DISK], 2, 4, "MOTOR=%01X WRRDY=%01X", | |
| oric->pravetz.drv[i].motor_on, | |
| oric->pravetz.drv[i].write_ready ); | |
| tzprintfpos( tz[TZ_DISK], 2, 5, "OVRAM=%s", oric->pravetz.olay ? "ON " : "OFF" ); | |
| return; | |
| } | |
| opname = "Unknown "; | |
| switch( oric->wddisk.currentop ) | |
| { | |
| case COP_NUFFINK: opname = "Idle "; break; | |
| case COP_READ_TRACK: opname = "Read track "; break; | |
| case COP_READ_SECTOR: opname = "Read sector "; break; | |
| case COP_READ_SECTORS: opname = "Read sectors "; break; | |
| case COP_WRITE_TRACK: opname = "Write track "; break; | |
| case COP_WRITE_SECTOR: opname = "Write sector "; break; | |
| case COP_WRITE_SECTORS: opname = "Write sectors"; break; | |
| case COP_READ_ADDRESS: opname = "Read address "; break; | |
| } | |
| tzprintfpos( tz[TZ_DISK], 2, 2, "STATUS=%02X ROMDIS=%1X", oric->wddisk.r_status, oric->romdis ); | |
| tzprintfpos( tz[TZ_DISK], 2, 3, "DRIVE=%02X SIDE=%02X TRACK=%02X", | |
| oric->wddisk.c_drive, | |
| oric->wddisk.c_side, | |
| oric->wddisk.c_track ); | |
| tzprintfpos( tz[TZ_DISK], 2, 4, "SECTR=%02X DATA=%02X", | |
| oric->wddisk.r_sector, | |
| oric->wddisk.r_data ); | |
| tzprintfpos( tz[TZ_DISK], 2, 5, "OP=%s", opname ); | |
| tzprintfpos( tz[TZ_DISK], 2, 6, "IRQC=%03d DRQC=%03d", | |
| oric->wddisk.delayedint, | |
| oric->wddisk.delayeddrq ); | |
| switch( oric->drivetype ) | |
| { | |
| case DRV_MICRODISC: | |
| tzprintfpos( tz[TZ_DISK], 2, 8, "MDSTAT=%02X INTRQ=%1X DRQ=%1X", | |
| oric->md.status, | |
| oric->md.intrq!=0, | |
| oric->md.drq!=0 ); | |
| tzprintfpos( tz[TZ_DISK], 2, 9, "EPROM=%1X", oric->md.diskrom ); | |
| break; | |
| case DRV_JASMIN: | |
| tzprintfpos( tz[TZ_DISK], 2, 8, "OVRAM=%s", oric->jasmin.olay ? "ON " : "OFF" ); | |
| break; | |
| } | |
| } | |
| void mon_state_reset( struct machine *oric ) | |
| { | |
| mwatch_oldvalid = SDL_FALSE; | |
| cpu_oldvalid = SDL_FALSE; | |
| ay_oldvalid = SDL_FALSE; | |
| via_oldvalid = SDL_FALSE; | |
| via2_oldvalid = SDL_FALSE; | |
| } | |
| void mon_update_mwatch( struct machine *oric ) | |
| { | |
| unsigned short addr; | |
| int j,k,l; | |
| unsigned int v; | |
| if( mw_split ) | |
| { | |
| tz[TZ_MEMWATCH]->tx[ 50] = mw_which==0 ? 14 : 5; | |
| tz[TZ_MEMWATCH]->tx[550] = mw_which==1 ? 14 : 5; | |
| } else { | |
| int offs = 10*tz[TZ_MEMWATCH]->w+1; | |
| for( k=0; k<48; k++ ) | |
| tz[TZ_MEMWATCH]->tx[offs+k] = 32; | |
| tz[TZ_MEMWATCH]->tx[ 50] = 5; | |
| tz[TZ_MEMWATCH]->tx[550] = 5; | |
| } | |
| addr = mw_addr[0]; | |
| for( j=0; j<19; j++, addr+=8 ) | |
| { | |
| if( ( mw_split ) && ( j == 9 ) ) | |
| { | |
| int offs = 10*tz[TZ_MEMWATCH]->w+1; | |
| for( k=0; k<48; k++ ) | |
| { | |
| tz[TZ_MEMWATCH]->tx[offs+k] = 2; | |
| tz[TZ_MEMWATCH]->bc[offs+k] = 3; | |
| tz[TZ_MEMWATCH]->fc[offs+k] = 2; | |
| } | |
| j++; | |
| addr = mw_addr[1]; | |
| } | |
| sprintf( vsptmp, "%04X ", addr ); | |
| for( k=0; k<8; k++ ) | |
| { | |
| char tmp[8]; | |
| snprintf( tmp, 7, "%02X ", mon_read( oric, addr+k ) ); | |
| strcat( vsptmp, tmp ); | |
| } | |
| l = (int)strlen( vsptmp ); | |
| vsptmp[l++] = 32; | |
| vsptmp[l++] = '\''; | |
| for( k=0; k<8; k++ ) | |
| { | |
| v = mon_read( oric, addr+k ); | |
| vsptmp[l++] = ((v>31)&&(v<128))?v:'.'; | |
| } | |
| vsptmp[l++] = '\''; | |
| vsptmp[l++] = 0; | |
| tzstrpos( tz[TZ_MEMWATCH], 1, j+1, vsptmp ); | |
| if( mwatch_oldvalid ) | |
| { | |
| for( k=0; k<8; k++ ) | |
| { | |
| if( isram( oric, addr+k ) && ( mwatch_old[addr+k] != mon_read( oric, addr+k ) ) ) | |
| { | |
| int offs = (j+1)*tz[TZ_MEMWATCH]->w; | |
| tz[TZ_MEMWATCH]->fc[offs+(k*3+7)] = 1; | |
| tz[TZ_MEMWATCH]->fc[offs+(k*3+8)] = 1; | |
| tz[TZ_MEMWATCH]->fc[offs+(k+33)] = 1; | |
| tz[TZ_MEMWATCH]->bc[offs+(k*3+7)] = 8; | |
| tz[TZ_MEMWATCH]->bc[offs+(k*3+8)] = 8; | |
| tz[TZ_MEMWATCH]->bc[offs+(k+33)] = 8; | |
| } | |
| } | |
| } | |
| } | |
| if( mw_mode == 0 ) return; | |
| makebox( tz[TZ_MEMWATCH], 17, 8, 7, 3, 2, 3 ); | |
| tzstrpos( tz[TZ_MEMWATCH], 18, 9, mw_ibuf ); | |
| } | |
| void mon_update( struct machine *oric ) | |
| { | |
| mon_update_regs( oric ); | |
| switch( mshow ) | |
| { | |
| case MSHOW_VIA: | |
| mon_update_via( oric, tz[TZ_VIA], &oric->via, &via_old, &via_oldvalid ); | |
| break; | |
| case MSHOW_VIA2: | |
| mon_update_via( oric, tz[TZ_VIA2], &oric->tele_via, &via2_old, &via2_oldvalid ); | |
| break; | |
| case MSHOW_AY: | |
| mon_update_ay( oric ); | |
| break; | |
| case MSHOW_DISK: | |
| mon_update_disk( oric ); | |
| break; | |
| } | |
| switch( cshow ) | |
| { | |
| case CSHOW_MWATCH: | |
| mon_update_mwatch( oric ); | |
| break; | |
| } | |
| } | |
| void mon_render( struct machine *oric ) | |
| { | |
| if (updatepreview) | |
| ula_renderscreen( oric ); | |
| oric->render_video( oric, SDL_FALSE ); | |
| switch( mshow ) | |
| { | |
| case MSHOW_VIA: | |
| oric->render_textzone( oric, TZ_VIA ); | |
| break; | |
| case MSHOW_VIA2: | |
| oric->render_textzone( oric, TZ_VIA2 ); | |
| break; | |
| case MSHOW_AY: | |
| oric->render_textzone( oric, TZ_AY ); | |
| break; | |
| case MSHOW_DISK: | |
| oric->render_textzone( oric, TZ_DISK ); | |
| break; | |
| } | |
| switch( cshow ) | |
| { | |
| case CSHOW_CONSOLE: | |
| oric->render_textzone( oric, TZ_MONITOR ); | |
| break; | |
| case CSHOW_DEBUG: | |
| oric->render_textzone( oric, TZ_DEBUG ); | |
| break; | |
| case CSHOW_MWATCH: | |
| oric->render_textzone( oric, TZ_MEMWATCH ); | |
| break; | |
| } | |
| oric->render_textzone( oric, TZ_REGS ); | |
| } | |
| void mon_hide_curs( void ) | |
| { | |
| struct textzone *ptz = tz[TZ_MONITOR]; | |
| int x = cursx-iloff; | |
| if( mon_asmmode ) | |
| { | |
| ptz->fc[ptz->w*19+8+x] = 2; | |
| ptz->bc[ptz->w*19+8+x] = 3; | |
| return; | |
| } | |
| if( ( x < 0 ) || ( x > CONS_WIDTH ) ) return; | |
| ptz->fc[ptz->w*19+2+x] = 2; | |
| ptz->bc[ptz->w*19+2+x] = 3; | |
| } | |
| void mon_show_curs( void ) | |
| { | |
| struct textzone *ptz = tz[TZ_MONITOR]; | |
| int x = cursx-iloff; | |
| if( mon_asmmode ) | |
| { | |
| ptz->fc[ptz->w*19+8+x] = 3; | |
| ptz->bc[ptz->w*19+8+x] = 2; | |
| return; | |
| } | |
| if( ( x < 0 ) || ( x > CONS_WIDTH ) ) return; | |
| ptz->fc[ptz->w*19+2+x] = 3; | |
| ptz->bc[ptz->w*19+2+x] = 2; | |
| } | |
| void mon_scroll( SDL_bool above ) | |
| { | |
| int x, y, s, d, h; | |
| struct textzone *ptz = tz[TZ_MONITOR]; | |
| h = above ? 17 : 18; | |
| s = ptz->w*2+1; | |
| d = ptz->w+1; | |
| for( y=0; y<h; y++ ) | |
| { | |
| for( x=0; x<48; x++ ) | |
| { | |
| ptz->tx[d] = ptz->tx[s]; | |
| ptz->fc[d] = ptz->fc[s]; | |
| ptz->bc[d++] = ptz->bc[s++]; | |
| } | |
| d += 2; | |
| s += 2; | |
| } | |
| for( x=0; x<48; x++ ) | |
| { | |
| ptz->tx[d] = ' '; | |
| ptz->fc[d] = 2; | |
| ptz->bc[d++] = 3; | |
| } | |
| } | |
| void mon_oprintf( char *fmt, ... ) | |
| { | |
| va_list ap; | |
| int i; | |
| char stmp[48]; | |
| va_start( ap, fmt ); | |
| if( vsnprintf( vsptmp, VSPTMPSIZE, fmt, ap ) != -1 ) | |
| { | |
| vsptmp[VSPTMPSIZE-1] = 0; | |
| i = 0; | |
| while( strlen( &vsptmp[i] ) > 47 ) | |
| { | |
| strncpy( stmp, &vsptmp[i], 47 ); | |
| stmp[47] = 0; | |
| tzstrpos( tz[TZ_MONITOR], 1, 19, stmp ); | |
| mon_scroll( SDL_FALSE ); | |
| i += 47; | |
| } | |
| tzstrpos( tz[TZ_MONITOR], 1, 19, &vsptmp[i] ); | |
| } | |
| va_end( ap ); | |
| } | |
| void mon_printf( char *fmt, ... ) | |
| { | |
| va_list ap; | |
| int i; | |
| char stmp[48]; | |
| mon_scroll( SDL_FALSE ); | |
| va_start( ap, fmt ); | |
| if( vsnprintf( vsptmp, VSPTMPSIZE, fmt, ap ) != -1 ) | |
| { | |
| vsptmp[VSPTMPSIZE-1] = 0; | |
| i = 0; | |
| while( strlen( &vsptmp[i] ) > 46 ) | |
| { | |
| strncpy( stmp, &vsptmp[i], 46 ); | |
| stmp[46] = 0; | |
| tzstrpos( tz[TZ_MONITOR], 1, 19, stmp ); | |
| mon_scroll( SDL_FALSE ); | |
| i += 46; | |
| } | |
| tzstrpos( tz[TZ_MONITOR], 1, 19, &vsptmp[i] ); | |
| } | |
| va_end( ap ); | |
| } | |
| void mon_printf_above( char *fmt, ... ) | |
| { | |
| va_list ap; | |
| int i; | |
| char stmp[48]; | |
| mon_scroll( SDL_TRUE ); | |
| va_start( ap, fmt ); | |
| if( vsnprintf( vsptmp, VSPTMPSIZE, fmt, ap ) != -1 ) | |
| { | |
| vsptmp[VSPTMPSIZE-1] = 0; | |
| i = 0; | |
| while( strlen( &vsptmp[i] ) > 46 ) | |
| { | |
| strncpy( stmp, &vsptmp[i], 46 ); | |
| stmp[46] = 0; | |
| tzstrpos( tz[TZ_MONITOR], 1, 18, stmp ); | |
| mon_scroll( SDL_TRUE ); | |
| i += 46; | |
| } | |
| tzstrpos( tz[TZ_MONITOR], 1, 18, &vsptmp[i] ); | |
| } | |
| va_end( ap ); | |
| } | |
| void mon_str( char *str ) | |
| { | |
| mon_scroll( SDL_FALSE ); | |
| tzstrpos( tz[TZ_MONITOR], 1, 19, str ); | |
| } | |
| void mon_str_above( char *str ) | |
| { | |
| mon_scroll( SDL_TRUE ); | |
| tzstrpos( tz[TZ_MONITOR], 1, 18, str ); | |
| } | |
| void mon_start_input( void ) | |
| { | |
| mon_scroll( SDL_FALSE ); | |
| ibuf[0] = 0; | |
| ilen = 0; | |
| iloff = 0; | |
| cursx = 0; | |
| if( mon_asmmode ) | |
| { | |
| tzsetcol( tz[TZ_MONITOR], 1, 3 ); | |
| tzprintfpos( tz[TZ_MONITOR], 1, 19, " %04X:", mon_addr ); | |
| return; | |
| } | |
| tzsetcol( tz[TZ_MONITOR], 1, 3 ); | |
| tzstrpos( tz[TZ_MONITOR], 1, 19, "]" ); | |
| } | |
| void mon_enter( struct machine *oric ) | |
| { | |
| defaultsyms.syms = NULL; | |
| defaultsyms.numsyms = 0; | |
| defaultsyms.symspace = -1; // Not a dynamic symbol table | |
| switch( oric->type ) | |
| { | |
| case MACH_ORIC1: | |
| case MACH_ORIC1_16K: | |
| case MACH_ATMOS: | |
| case MACH_PRAVETZ: | |
| defaultsyms.syms = defsym_atmos; | |
| defaultsyms.numsyms = sizeof( defsym_atmos ) / sizeof( struct msym ); | |
| break; | |
| case MACH_TELESTRAT: | |
| defaultsyms.syms = defsym_tele; | |
| defaultsyms.numsyms = sizeof( defsym_tele ) / sizeof( struct msym ); | |
| break; | |
| } | |
| if( mon_bpmsg[0] ) | |
| { | |
| mon_printf_above( mon_bpmsg ); | |
| mon_bpmsg[0] = 0; | |
| } | |
| modified = SDL_FALSE; | |
| updatepreview = SDL_TRUE; | |
| } | |
| void mon_warminit( struct machine *oric ) | |
| { | |
| mon_start_input(); | |
| mon_show_curs(); | |
| } | |
| void mon_init( struct machine *oric ) | |
| { | |
| defaultsyms.numsyms = 0; | |
| defaultsyms.symspace = 0; | |
| defaultsyms.syms = NULL; | |
| oric->usersyms.numsyms = 0; | |
| oric->usersyms.symspace = 0; | |
| oric->usersyms.syms = NULL; | |
| mon_bpmsg[0] = 0; | |
| mshow = MSHOW_VIA; | |
| cshow = CSHOW_CONSOLE; | |
| mon_asmmode = SDL_FALSE; | |
| mon_start_input(); | |
| mon_show_curs(); | |
| mon_addr = oric->cpu.pc; | |
| lastcmd = 0; | |
| mw_split = SDL_FALSE; | |
| mw_which = 0; | |
| mwatch_oldvalid = SDL_FALSE; | |
| cpu_oldvalid = SDL_FALSE; | |
| ay_oldvalid = SDL_FALSE; | |
| via_oldvalid = SDL_FALSE; | |
| #if LOG_DEBUG | |
| debug_logfile = fopen( debug_logname, "w" ); | |
| #endif | |
| } | |
| void mon_shut( struct machine *oric ) | |
| { | |
| mon_freesyms( &oric->usersyms ); | |
| #if LOG_DEBUG | |
| if( debug_logfile ) fclose( debug_logfile ); | |
| debug_logfile = NULL; | |
| #endif | |
| } | |
| int mon_getreg( char *buf, int *off, SDL_bool addrregs, SDL_bool nregs, SDL_bool viaregs ) | |
| { | |
| int i; | |
| i = *off; | |
| while( isws( buf[i] ) ) i++; | |
| if( viaregs ) | |
| { | |
| if( strncasecmp( &buf[i], "vpcr", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_PCR; | |
| } | |
| if( strncasecmp( &buf[i], "vacr", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_ACR; | |
| } | |
| if( strncasecmp( &buf[i], "vsr", 3 ) == 0 ) | |
| { | |
| i+=3; | |
| *off = i; | |
| return REG_VIA_SR; | |
| } | |
| if( strncasecmp( &buf[i], "vifr", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_IFR; | |
| } | |
| if( strncasecmp( &buf[i], "vier", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_IER; | |
| } | |
| if( strncasecmp( &buf[i], "vira", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_IRA; | |
| } | |
| if( strncasecmp( &buf[i], "vora", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_ORA; | |
| } | |
| if( strncasecmp( &buf[i], "vddra", 5 ) == 0 ) | |
| { | |
| i+=5; | |
| *off = i; | |
| return REG_VIA_DDRA; | |
| } | |
| if( strncasecmp( &buf[i], "virb", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_IRB; | |
| } | |
| if( strncasecmp( &buf[i], "vorb", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_ORB; | |
| } | |
| if( strncasecmp( &buf[i], "vddrb", 5 ) == 0 ) | |
| { | |
| i+=5; | |
| *off = i; | |
| return REG_VIA_DDRB; | |
| } | |
| if( strncasecmp( &buf[i], "vt1l", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_T1L; | |
| } | |
| if( strncasecmp( &buf[i], "vt1c", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_T1C; | |
| } | |
| if( strncasecmp( &buf[i], "vt2l", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_T2L; | |
| } | |
| if( strncasecmp( &buf[i], "vt2c", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_T2C; | |
| } | |
| if( strncasecmp( &buf[i], "vca1", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_CA1; | |
| } | |
| if( strncasecmp( &buf[i], "vca2", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_CA2; | |
| } | |
| if( strncasecmp( &buf[i], "vcb1", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_CB1; | |
| } | |
| if( strncasecmp( &buf[i], "vcb2", 4 ) == 0 ) | |
| { | |
| i+=4; | |
| *off = i; | |
| return REG_VIA_CA2; | |
| } | |
| } | |
| if( addrregs ) | |
| { | |
| if( strncasecmp( &buf[i], "pc", 2 ) == 0 ) | |
| { | |
| i+=2; | |
| *off = i; | |
| return REG_PC; | |
| } | |
| if( strncasecmp( &buf[i], "sp", 2 ) == 0 ) | |
| { | |
| i+=2; | |
| *off = i; | |
| return REG_SP; | |
| } | |
| } | |
| if( nregs ) | |
| { | |
| switch( buf[i] ) | |
| { | |
| case 'a': | |
| case 'A': | |
| i++; | |
| *off = i; | |
| return REG_A; | |
| case 'x': | |
| case 'X': | |
| i++; | |
| *off = i; | |
| return REG_X; | |
| case 'y': | |
| case 'Y': | |
| i++; | |
| *off = i; | |
| return REG_Y; | |
| } | |
| } | |
| return -1; | |
| } | |
| SDL_bool mon_getnum( struct machine *oric, unsigned int *num, char *buf, int *off, SDL_bool addrregs, SDL_bool nregs, SDL_bool viaregs, SDL_bool symbols ) | |
| { | |
| int i, j; | |
| char c; | |
| unsigned int v; | |
| i = *off; | |
| while( isws( buf[i] ) ) i++; | |
| if( ( symbols ) && ( issymstart( buf[i] ) ) ) | |
| { | |
| struct msym *fsym; | |
| for( j=0; issymchar( buf[i+j] ); j++ ) ; | |
| c = buf[i+j]; | |
| if( isws( c ) || ( c == 13 ) || ( c == 10 ) || ( c == 0 ) || ( c == ',' ) || ( c == ')' ) ) | |
| { | |
| buf[i+j] = 0; | |
| fsym = mon_find_sym_by_name( oric, &buf[i] ); | |
| buf[i+j] = c; | |
| if( fsym ) | |
| { | |
| (*num) = fsym->addr; | |
| (*off) = i+j; | |
| return SDL_TRUE; | |
| } | |
| } | |
| } | |
| j = mon_getreg( buf, off, addrregs, nregs, viaregs ); | |
| if( j != -1 ) | |
| { | |
| switch( j ) | |
| { | |
| case REG_A: | |
| *num = oric->cpu.a; | |
| return SDL_TRUE; | |
| case REG_X: | |
| *num = oric->cpu.x; | |
| return SDL_TRUE; | |
| case REG_Y: | |
| *num = oric->cpu.y; | |
| return SDL_TRUE; | |
| case REG_PC: | |
| *num = oric->cpu.pc; | |
| return SDL_TRUE; | |
| case REG_SP: | |
| *num = oric->cpu.sp|0x100; | |
| return SDL_TRUE; | |
| case REG_VIA_PCR: | |
| *num = oric->via.pcr; | |
| return SDL_TRUE; | |
| case REG_VIA_ACR: | |
| *num = oric->via.acr; | |
| return SDL_TRUE; | |
| case REG_VIA_SR: | |
| *num = oric->via.sr; | |
| return SDL_TRUE; | |
| case REG_VIA_IFR: | |
| *num = oric->via.ifr; | |
| return SDL_TRUE; | |
| case REG_VIA_IER: | |
| *num = oric->via.ier; | |
| return SDL_TRUE; | |
| case REG_VIA_IRA: | |
| *num = oric->via.ira; | |
| return SDL_TRUE; | |
| case REG_VIA_ORA: | |
| *num = oric->via.ora; | |
| return SDL_TRUE; | |
| case REG_VIA_DDRA: | |
| *num = oric->via.ddra; | |
| return SDL_TRUE; | |
| case REG_VIA_IRB: | |
| *num = oric->via.irb; | |
| return SDL_TRUE; | |
| case REG_VIA_ORB: | |
| *num = oric->via.orb; | |
| return SDL_TRUE; | |
| case REG_VIA_DDRB: | |
| *num = oric->via.ddrb; | |
| return SDL_TRUE; | |
| case REG_VIA_T1L: | |
| *num = (oric->via.t1l_h<<8)|oric->via.t1l_l; | |
| return SDL_TRUE; | |
| case REG_VIA_T1C: | |
| *num = oric->via.t1c; | |
| return SDL_TRUE; | |
| case REG_VIA_T2L: | |
| *num = (oric->via.t2l_h<<8)|oric->via.t2l_l; | |
| return SDL_TRUE; | |
| case REG_VIA_T2C: | |
| *num = oric->via.t2c; | |
| return SDL_TRUE; | |
| case REG_VIA_CA1: | |
| *num = oric->via.ca1; | |
| return SDL_TRUE; | |
| case REG_VIA_CA2: | |
| *num = oric->via.ca2; | |
| return SDL_TRUE; | |
| case REG_VIA_CB1: | |
| *num = oric->via.cb1; | |
| return SDL_TRUE; | |
| case REG_VIA_CB2: | |
| *num = oric->via.cb2; | |
| return SDL_TRUE; | |
| } | |
| } | |
| if( buf[i] == '%' ) | |
| { | |
| // Binary | |
| i++; | |
| if( !isbin( buf[i] ) ) return SDL_FALSE; | |
| v = 0; | |
| while( isbin( buf[i] ) ) | |
| { | |
| v = (v<<1) | (buf[i]-'0'); | |
| i++; | |
| } | |
| *num = v; | |
| *off = i; | |
| return SDL_TRUE; | |
| } | |
| if( buf[i] == '$' || buf[i] == '#' ) | |
| { | |
| // Hex | |
| i++; | |
| if( !ishex( buf[i] ) ) return SDL_FALSE; | |
| v = 0; | |
| for( ;; ) | |
| { | |
| j = hexit( buf[i] ); | |
| if( j == -1 ) break; | |
| v = (v<<4) | j; | |
| i++; | |
| } | |
| *num = v; | |
| *off = i; | |
| return SDL_TRUE; | |
| } | |
| if( !isnum( buf[i] ) ) return SDL_FALSE; | |
| v = 0; | |
| while( isnum( buf[i] ) ) | |
| { | |
| v = (v*10) + (buf[i]-'0'); | |
| i++; | |
| } | |
| *num = v; | |
| *off = i; | |
| return SDL_TRUE; | |
| } | |
| Uint16 mon_sym_best_guess( struct machine *oric, Uint16 addr, char *symname, SDL_bool use_emu_state ) | |
| { | |
| // In the ROM area? | |
| if( addr >= 0xc000 ) | |
| { | |
| // In a telestrat bank? | |
| if( oric->type == MACH_TELESTRAT ) | |
| { | |
| // Labels starting t0_ are assumed to be telestrat bank 0 (etc.) | |
| if( ( symname[0] == 't' ) && | |
| ( ( symname[1] >= '0' ) && ( symname[1] <= '7' ) ) && | |
| ( symname[2] == '_' ) ) | |
| return SYMF_TELEBANK0 << (symname[1]-'0'); | |
| // No hint from the label name. Can we attempt to use the current telestrat bank? | |
| if( use_emu_state ) | |
| return SYMF_TELEBANK0 << oric->tele_currbank; | |
| // Just make it valid in any telestrat bank | |
| return SYMF_TELEBANK0|SYMF_TELEBANK1|SYMF_TELEBANK2|SYMF_TELEBANK3|SYMF_TELEBANK4|SYMF_TELEBANK5|SYMF_TELEBANK6|SYMF_TELEBANK7; | |
| } | |
| // Its not a telestrat, so its ROM or overlay | |
| if( use_emu_state ) | |
| { | |
| int romdis = oric->romdis; | |
| if( ( oric->drivetype == DRV_JASMIN ) && ( oric->jasmin.olay ) ) | |
| romdis = 1; | |
| return romdis ? SYMF_ROMDIS1 : SYMF_ROMDIS0; | |
| } | |
| return SYMF_ROMDIS1; | |
| } | |
| // Normal memory | |
| return 0; | |
| } | |
| struct msym *mon_replace_or_add_symbol( struct symboltable *stab, struct machine *oric, char *symname, unsigned short flags, Uint16 addr ) | |
| { | |
| int i; | |
| char symtmp[160]; | |
| struct msym *retval = NULL; | |
| for( i=0; issymchar(symname[i]); i++ ) | |
| symtmp[i] = symname[i]; | |
| symtmp[i] = 0; | |
| // Is it a dynamic symbol table? | |
| if( stab->symspace == -1 ) return retval; | |
| if( flags == SYM_BESTGUESS ) | |
| flags = mon_sym_best_guess( oric, addr, symtmp, SDL_TRUE ); | |
| for( i=0; i<stab->numsyms; i++ ) | |
| { | |
| if( !oric->symbolscase ) | |
| { | |
| if( strcasecmp( symtmp, stab->syms[i].name ) == 0 ) | |
| break; | |
| } else { | |
| if( strcmp( symtmp, stab->syms[i].name ) == 0 ) | |
| break; | |
| } | |
| } | |
| // Replace existing symbol? | |
| if( i < stab->numsyms ) | |
| { | |
| stab->syms[i].addr = addr; | |
| stab->syms[i].flags = flags; | |
| return &stab->syms[i]; | |
| } | |
| mon_addsym( stab, addr, flags, symtmp, &retval ); | |
| return retval; | |
| } | |
| SDL_bool mon_symsfromsnapshot( struct symboltable *stab, unsigned char *buffer, unsigned int len) | |
| { | |
| int offs, symlen, addr, flags; | |
| char *symname; | |
| stab->numsyms = 0; | |
| offs = 0; | |
| while (offs < len) | |
| { | |
| symlen = (buffer[offs]<<24)|(buffer[offs+1]<<16)|(buffer[offs+2]<<8)|buffer[offs+3]; | |
| offs+=4; | |
| if (symlen+offs >= len) return SDL_FALSE; | |
| symname = (char *)(&buffer[offs]); | |
| offs += symlen; | |
| addr = (buffer[offs]<<8)|buffer[offs+1]; | |
| offs += 2; | |
| flags = (buffer[offs]<<8)|buffer[offs+1]; | |
| offs += 2; | |
| mon_addsym( stab, addr, flags, symname, NULL ); | |
| } | |
| return SDL_TRUE; | |
| } | |
| SDL_bool mon_new_symbols( struct symboltable *stab, struct machine *oric, char *fname, unsigned short flags, SDL_bool above, SDL_bool verbose ) | |
| { | |
| FILE *f; | |
| int i, j; | |
| unsigned int v; | |
| f = fopen( fname, "r" ); | |
| if( !f ) | |
| { | |
| if( verbose ) | |
| { | |
| if( above ) | |
| mon_printf_above( "Unable to open '%s'", fname ); | |
| else | |
| mon_printf( "Unable to open '%s'", fname ); | |
| } | |
| return SDL_FALSE; | |
| } | |
| stab->numsyms = 0; | |
| while( !feof( f ) ) | |
| { | |
| char linetmp[256]; | |
| if( !fgets( linetmp, 256, f ) ) break; | |
| if( sscanf( linetmp, "al %06X .%s", &v, linetmp ) != 2 ) | |
| { | |
| for( i=0, v=0; i<4; i++ ) | |
| { | |
| j = hexit( linetmp[i] ); | |
| if( j == -1 ) break; | |
| v = (v<<4)|j; | |
| } | |
| if( i < 4 ) continue; | |
| if( linetmp[4] != 32 ) continue; | |
| if( !issymstart( linetmp[5] ) ) continue; | |
| for( i=5,j=0; issymchar(linetmp[i]); i++,j++ ) | |
| linetmp[j] = linetmp[i]; | |
| linetmp[j] = 0; | |
| } | |
| // printf( "'%s' = %04X\n", linetmp, v ); | |
| fflush( stdout ); | |
| // Guess the flags! | |
| if( flags == SYM_BESTGUESS ) | |
| { | |
| mon_addsym( stab, v, mon_sym_best_guess( oric, v, linetmp, SDL_FALSE ), linetmp, NULL ); | |
| } else { | |
| mon_addsym( stab, v, flags, linetmp, NULL ); | |
| } | |
| } | |
| fclose( f ); | |
| if( verbose ) | |
| { | |
| if( above ) | |
| mon_printf_above( "Symbols loaded from '%s'", fname ); | |
| else | |
| mon_printf( "Symbols loaded from '%s'", fname ); | |
| } | |
| return SDL_TRUE; | |
| } | |
| SDL_bool mon_cmd( char *cmd, struct machine *oric, SDL_bool *needrender ) | |
| { | |
| int i, j, k, l; | |
| unsigned int v, w; | |
| SDL_bool done = SDL_FALSE; | |
| unsigned char *tmem; | |
| struct msym *tmpsym; | |
| FILE *f; | |
| i=0; | |
| while( isws( cmd[i] ) ) i++; | |
| if( cmd[i] != '?' ) | |
| helpcount = 0; | |
| switch( cmd[i] ) | |
| { | |
| case 'a': | |
| lastcmd = ARPT_ASSEM; | |
| i++; | |
| if( mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| mon_addr = v; | |
| mon_asmmode = SDL_TRUE; | |
| break; | |
| case 's': // Symbols | |
| lastcmd = 0; | |
| i++; | |
| switch( cmd[i] ) | |
| { | |
| case 'c': // Case insensitive | |
| oric->symbolscase = SDL_FALSE; | |
| mon_str( "Symbols are not case-sensitive" ); | |
| break; | |
| case 'C': // Case sensitive | |
| oric->symbolscase = SDL_TRUE; | |
| mon_str( "Symbols are case-sensitive" ); | |
| break; | |
| case 'a': // add | |
| if( !isws( cmd[i+1] ) ) | |
| { | |
| mon_str( "???" ); | |
| break; | |
| } | |
| i+=2; | |
| while( isws( cmd[i] ) ) i++; | |
| if( !issymstart( cmd[i] ) ) | |
| { | |
| mon_str( "Expected symbol name and address" ); | |
| break; | |
| } | |
| j = i; | |
| while( issymchar( cmd[i] ) ) i++; | |
| if( !isws( cmd[i] ) ) | |
| { | |
| mon_str( "Expected symbol name and address" ); | |
| break; | |
| } | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Address expected" ); | |
| break; | |
| } | |
| tmpsym = mon_replace_or_add_symbol( &oric->usersyms, oric, &cmd[j], SYM_BESTGUESS, v ); | |
| if( !tmpsym ) | |
| { | |
| mon_str( "Failed for some reason" ); | |
| break; | |
| } | |
| mon_printf( "%s = %04X", tmpsym->name, tmpsym->addr ); | |
| break; | |
| case 'k': // kill | |
| if( !isws( cmd[i+1] ) ) | |
| { | |
| mon_str( "???" ); | |
| break; | |
| } | |
| i+=2; | |
| while( isws( cmd[i] ) ) i++; | |
| if( !issymstart( cmd[i] ) ) | |
| { | |
| mon_str( "Symbol expected" ); | |
| break; | |
| } | |
| j = i; | |
| while( issymchar( cmd[i] ) ) i++; | |
| if( cmd[i] != 0 ) | |
| { | |
| mon_printf( "Expected end of line at '%s'", &cmd[i] ); | |
| break; | |
| } | |
| if( !mon_tab_find_sym_by_name( &oric->usersyms, oric, &cmd[j], &k ) ) | |
| { | |
| mon_printf( "Couldn't find '%s' in the user symbol table", &cmd[j] ); | |
| break; | |
| } | |
| for( ; k<(oric->usersyms.numsyms-1); k++ ) | |
| oric->usersyms.syms[k] = oric->usersyms.syms[k+1]; | |
| oric->usersyms.numsyms--; | |
| mon_printf( "Killed symbol '%s'", &cmd[j] ); | |
| break; | |
| case 'z': // Zap | |
| oric->usersyms.numsyms = 0; | |
| mon_str( "Symbols zapped!" ); | |
| break; | |
| case 'l': // Load | |
| if( !isws( cmd[i+1] ) ) | |
| { | |
| mon_str( "???" ); | |
| break; | |
| } | |
| i+=2; | |
| mon_new_symbols( &oric->usersyms, oric, &cmd[i], SYM_BESTGUESS, SDL_FALSE, SDL_TRUE ); | |
| break; | |
| case 'x': // Export | |
| if( !isws( cmd[i+1] ) ) | |
| { | |
| mon_str( "???" ); | |
| break; | |
| } | |
| i+=2; | |
| f = fopen( &cmd[i], "w" ); | |
| if( !f ) | |
| { | |
| mon_printf( "Unable to open '%s' for writing", &cmd[i] ); | |
| break; | |
| } | |
| for( j=0; j<oric->usersyms.numsyms; j++ ) | |
| fprintf( f, "%04X %s\n", oric->usersyms.syms[j].addr, oric->usersyms.syms[j].name ); | |
| fclose( f ); | |
| mon_printf( "User symbols exported to '%s'", &cmd[i] ); | |
| break; | |
| default: | |
| mon_str( "???" ); | |
| break; | |
| } | |
| break; | |
| case 'b': | |
| lastcmd = 0; | |
| i++; | |
| switch( cmd[i] ) | |
| { | |
| case 'l': | |
| if( cmd[i+1] == 'm' ) | |
| { | |
| oric->cpu.anymbp = SDL_FALSE; | |
| for( j=0; j<16; j++ ) | |
| { | |
| if( oric->cpu.membreakpoints[j].flags ) | |
| { | |
| mon_printf( "%02d: $%04X %c%c%c", | |
| j, | |
| oric->cpu.membreakpoints[j].addr, | |
| (oric->cpu.membreakpoints[j].flags&MBPF_READ) ? 'r' : ' ', | |
| (oric->cpu.membreakpoints[j].flags&MBPF_WRITE) ? 'w' : ' ', | |
| (oric->cpu.membreakpoints[j].flags&MBPF_CHANGE) ? 'c' : ' ' ); | |
| oric->cpu.anymbp = SDL_TRUE; | |
| } | |
| } | |
| break; | |
| } | |
| oric->cpu.anybp = SDL_FALSE; | |
| for( j=0; j<16; j++ ) | |
| { | |
| if( oric->cpu.breakpoints[j] != -1 ) | |
| { | |
| mon_printf( "%02d: $%04X %s%s", | |
| j, | |
| oric->cpu.breakpoints[j], | |
| (oric->cpu.breakpoint_flags[j]&MBPF_RESETCYCLES) ? "z" : "", | |
| (oric->cpu.breakpoint_flags[j]&MBPF_RESETCYCLESCONTINUE) ? "c" : ""); | |
| oric->cpu.anybp = SDL_TRUE; | |
| } | |
| } | |
| break; | |
| case 's': | |
| if( cmd[i+1] == 'm' ) | |
| { | |
| for( j=0; j<16; j++ ) | |
| { | |
| if( oric->cpu.membreakpoints[j].flags == 0 ) | |
| break; | |
| } | |
| if( j == 16 ) | |
| { | |
| mon_str( "Max 16 breakpoints" ); | |
| break; | |
| } | |
| i += 2; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_TRUE, SDL_TRUE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Address expected" ); | |
| break; | |
| } | |
| oric->cpu.membreakpoints[j].addr = v & 0xffff; | |
| oric->cpu.membreakpoints[j].lastval = mon_read( oric, v&0xffff ); | |
| oric->cpu.membreakpoints[j].flags = 0; | |
| while( isws( cmd[i] ) ) i++; | |
| for( ;; ) | |
| { | |
| switch( cmd[i] ) | |
| { | |
| case 'r': | |
| oric->cpu.membreakpoints[j].flags |= MBPF_READ; | |
| i++; | |
| continue; | |
| case 'w': | |
| oric->cpu.membreakpoints[j].flags |= MBPF_WRITE; | |
| i++; | |
| continue; | |
| case 'c': | |
| oric->cpu.membreakpoints[j].flags |= MBPF_CHANGE; | |
| i++; | |
| continue; | |
| } | |
| break; | |
| } | |
| if( !oric->cpu.membreakpoints[j].flags ) | |
| oric->cpu.membreakpoints[j].flags = MBPF_READ|MBPF_WRITE; | |
| oric->cpu.anymbp = SDL_TRUE; | |
| mon_printf( "m%02d: $%04X %s%s%s", j, oric->cpu.membreakpoints[j].addr, | |
| (oric->cpu.membreakpoints[j].flags&MBPF_READ) ? "r" : "", | |
| (oric->cpu.membreakpoints[j].flags&MBPF_WRITE) ? "w" : "", | |
| (oric->cpu.membreakpoints[j].flags&MBPF_CHANGE) ? "c" : "" ); | |
| break; | |
| } | |
| for( j=0; j<16; j++ ) | |
| { | |
| if( oric->cpu.breakpoints[j] == -1 ) | |
| break; | |
| } | |
| if( j == 16 ) | |
| { | |
| mon_str( "Max 16 breakpoints" ); | |
| break; | |
| } | |
| i++; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_TRUE, SDL_TRUE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Address expected" ); | |
| break; | |
| } | |
| oric->cpu.breakpoints[j] = v & 0xffff; | |
| oric->cpu.breakpoint_flags[j] = 0; | |
| oric->cpu.anybp = SDL_TRUE; | |
| while( isws( cmd[i] ) ) i++; | |
| for( ;; ) | |
| { | |
| switch( cmd[i] ) | |
| { | |
| case 'z': | |
| oric->cpu.breakpoint_flags[j] |= MBPF_RESETCYCLES; | |
| i++; | |
| continue; | |
| case 'c': | |
| oric->cpu.breakpoint_flags[j] |= MBPF_RESETCYCLESCONTINUE; | |
| i++; | |
| continue; | |
| } | |
| break; | |
| } | |
| mon_printf( "%02d: $%04X %s%s", | |
| j, | |
| oric->cpu.breakpoints[j], | |
| (oric->cpu.breakpoint_flags[j]&MBPF_RESETCYCLES) ? "z" : "", | |
| (oric->cpu.breakpoint_flags[j]&MBPF_RESETCYCLESCONTINUE) ? "c" : "" ); | |
| break; | |
| case 'c': | |
| j = 0; | |
| if( cmd[i+1] == 'm' ) | |
| { | |
| j = 1; | |
| i++; | |
| } | |
| i++; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_FALSE, SDL_FALSE, SDL_FALSE, SDL_FALSE ) ) | |
| { | |
| mon_str( "Breakpoint ID expected" ); | |
| break; | |
| } | |
| if( v > 15 ) | |
| { | |
| mon_str( "Invalid breakpoint ID" ); | |
| break; | |
| } | |
| if( j ) | |
| { | |
| oric->cpu.membreakpoints[v].flags = 0; | |
| oric->cpu.anymbp = SDL_FALSE; | |
| for( j=0; j<16; j++ ) | |
| { | |
| if( oric->cpu.membreakpoints[j].flags != 0 ) | |
| { | |
| oric->cpu.anymbp = SDL_TRUE; | |
| break; | |
| } | |
| } | |
| break; | |
| } | |
| oric->cpu.breakpoints[v] = -1; | |
| oric->cpu.anybp = SDL_FALSE; | |
| for( j=0; j<16; j++ ) | |
| { | |
| if( oric->cpu.breakpoints[j] != -1 ) | |
| { | |
| oric->cpu.anybp = SDL_TRUE; | |
| break; | |
| } | |
| } | |
| break; | |
| case 'z': | |
| if( cmd[i+1] == 'm' ) | |
| { | |
| for( i=0; i<16; i++ ) | |
| oric->cpu.membreakpoints[i].flags = 0; | |
| oric->cpu.anymbp = SDL_FALSE; | |
| break; | |
| } | |
| for( i=0; i<16; i++ ) | |
| oric->cpu.breakpoints[i] = -1; | |
| oric->cpu.anybp = SDL_FALSE; | |
| break; | |
| default: | |
| mon_str( "???" ); | |
| break; | |
| } | |
| break; | |
| case 'm': | |
| lastcmd = ARPT_MEMORY; | |
| i++; | |
| switch( cmd[i] ) | |
| { | |
| case 's': | |
| lastcmd = 0; | |
| i++; | |
| if( !mon_getnum( oric, &w, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Value expected" ); | |
| break; | |
| } | |
| memory_search_pos = 0; | |
| uint16_t* collection = memory_search; | |
| memory_hits = 0; | |
| for (int j=0x500; j < 0x9800; j++){ | |
| unsigned char byte = mon_read( oric, j ); | |
| if ((unsigned char)w == byte){ | |
| *collection++ = j; | |
| memory_hits++; | |
| } | |
| } | |
| sprintf( vsptmp, "Found %i match(es)", memory_hits ); | |
| mon_str(vsptmp); | |
| break; | |
| case 'r': | |
| lastcmd = 0; | |
| i++; | |
| if( !mon_getnum( oric, &w, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Value expected" ); | |
| break; | |
| } | |
| memory_search_pos = 0; | |
| int newhits = 0; | |
| for (int j = 0; j < memory_hits; j++){ | |
| int16_t curr_mem_addr = memory_search[j]; | |
| unsigned char byte = mon_read( oric, curr_mem_addr ); | |
| if ((unsigned char)w == byte){ | |
| memory_search[newhits++] = curr_mem_addr; | |
| } | |
| } | |
| memory_hits = newhits; | |
| sprintf( vsptmp, "Refined match(es) : %i", memory_hits ); | |
| mon_str( vsptmp ); | |
| break; | |
| case 'p': | |
| { | |
| lastcmd = ARPT_SEARCH; | |
| int lines = 0; | |
| char tmp[16]; | |
| int j, k = 0; | |
| vsptmp[0] = 0; | |
| for (j = memory_search_pos; j < memory_hits; j++, k++){ | |
| unsigned char byte = mon_read( oric, memory_search[j] ); | |
| sprintf( tmp, "[%04X]:[%02X] ", memory_search[j], byte ); | |
| strcat( vsptmp, tmp ); | |
| if (k == 4){ | |
| mon_str( vsptmp ); | |
| vsptmp[0] = 0; | |
| lines++; | |
| k = 0; | |
| } | |
| if (lines > 16){ | |
| memory_search_pos = j; | |
| break; | |
| } | |
| } | |
| if (strlen( vsptmp )){ | |
| mon_str( vsptmp ); | |
| } | |
| if ( j >= memory_hits ){ | |
| memory_search_pos = 0; | |
| lastcmd = 0; | |
| } | |
| break; | |
| } | |
| case 'm': | |
| lastcmd = 0; | |
| i++; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Bad address" ); | |
| break; | |
| } | |
| if( !mon_getnum( oric, &w, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Value expected" ); | |
| break; | |
| } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, v, w ); | |
| updatepreview = SDL_TRUE; | |
| break; | |
| case 'w': | |
| lastcmd = 0; | |
| i++; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Bad address" ); | |
| break; | |
| } | |
| if( mw_split ) | |
| { | |
| mw_addr[mw_which] = v; | |
| } else { | |
| mw_which = 0; | |
| mw_addr[0] = v; | |
| } | |
| cshow = CSHOW_MWATCH; | |
| break; | |
| default: | |
| if( ( cmd[i] != 0 ) && ( !isws( cmd[i] ) ) ) | |
| { | |
| mon_str( "???" ); | |
| break; | |
| } | |
| if( mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| mon_addr = v; | |
| for( j=0; j<16; j++ ) | |
| { | |
| sprintf( vsptmp, "%04X ", mon_addr ); | |
| for( k=0; k<8; k++ ) | |
| { | |
| char tmp[8]; | |
| snprintf( tmp, 7, "%02X ", mon_read( oric, mon_addr+k ) ); | |
| strcat( vsptmp, tmp ); | |
| } | |
| l = (int)strlen( vsptmp ); | |
| vsptmp[l++] = 32; | |
| vsptmp[l++] = '\''; | |
| for( k=0; k<8; k++ ) | |
| { | |
| v = mon_read( oric, mon_addr++ ); | |
| vsptmp[l++] = ((v>31)&&(v<128))?v:'.'; | |
| } | |
| vsptmp[l++] = '\''; | |
| vsptmp[l++] = 0; | |
| mon_str( vsptmp ); | |
| } | |
| break; | |
| } | |
| break; | |
| case 'd': | |
| lastcmd = ARPT_DISASM; | |
| i++; | |
| if( mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| mon_addr = v; | |
| for( j=0; j<16; j++ ) | |
| mon_str( mon_disassemble( oric, &mon_addr, NULL, SDL_FALSE ) ); | |
| break; | |
| case 'r': | |
| lastcmd = 0; | |
| i++; | |
| j = mon_getreg( cmd, &i, SDL_TRUE, SDL_TRUE, SDL_TRUE ); | |
| if( j == -1 ) | |
| { | |
| mon_str( "Register expected" ); | |
| break; | |
| } | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_TRUE, SDL_TRUE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Expression expected" ); | |
| break; | |
| } | |
| switch( j ) | |
| { | |
| case REG_PC: mon_set_modified( oric ); oric->cpu.pc = v; break; | |
| case REG_SP: mon_set_modified( oric ); oric->cpu.sp = v; break; | |
| case REG_A: mon_set_modified( oric ); oric->cpu.a = v; break; | |
| case REG_X: mon_set_modified( oric ); oric->cpu.x = v; break; | |
| case REG_Y: mon_set_modified( oric ); oric->cpu.y = v; break; | |
| case REG_VIA_PCR: mon_set_modified( oric ); via_write( &oric->via, VIA_PCR, v ); break; | |
| case REG_VIA_ACR: mon_set_modified( oric ); via_write( &oric->via, VIA_ACR, v ); break; | |
| case REG_VIA_SR: mon_set_modified( oric ); via_write( &oric->via, VIA_SR, v ); break; | |
| case REG_VIA_IFR: mon_set_modified( oric ); via_mon_write_ifr( &oric->via, v ); break; | |
| case REG_VIA_IER: mon_set_modified( oric ); oric->via.ier = v&0x7f; break; | |
| case REG_VIA_IRA: mon_set_modified( oric ); oric->via.write_port_a( &oric->via, 0xff, v ); break; | |
| case REG_VIA_ORA: mon_set_modified( oric ); via_write( &oric->via, VIA_IORA, v ); break; | |
| case REG_VIA_DDRA: mon_set_modified( oric ); via_write( &oric->via, VIA_DDRA, v ); break; | |
| case REG_VIA_IRB: mon_set_modified( oric ); oric->via.write_port_b( &oric->via, 0xff, v ); break; | |
| case REG_VIA_ORB: mon_set_modified( oric ); via_write( &oric->via, VIA_IORB, v ); break; | |
| case REG_VIA_DDRB: mon_set_modified( oric ); via_write( &oric->via, VIA_DDRB, v ); break; | |
| case REG_VIA_T1C: mon_set_modified( oric ); oric->via.t1c = v; break; | |
| case REG_VIA_CA1: mon_set_modified( oric ); via_write_CA1( &oric->via, v ); break; | |
| case REG_VIA_CA2: mon_set_modified( oric ); via_write_CA2( &oric->via, v ); break; | |
| case REG_VIA_CB1: mon_set_modified( oric ); via_write_CB1( &oric->via, v ); break; | |
| case REG_VIA_CB2: mon_set_modified( oric ); via_write_CB2( &oric->via, v ); break; | |
| case REG_VIA_T2C: mon_set_modified( oric ); oric->via.t2c = v; break; | |
| case REG_VIA_T1L: | |
| mon_set_modified( oric ); | |
| via_write( &oric->via, VIA_T1L_L, v&0xff ); | |
| via_write( &oric->via, VIA_T1L_H, (v>>8)&0xff ); | |
| break; | |
| case REG_VIA_T2L: | |
| mon_set_modified( oric ); | |
| via_write( &oric->via, VIA_T2C_L, v&0xff ); | |
| via_write( &oric->via, VIA_T2C_H, (v>>8)&0xff ); | |
| break; | |
| } | |
| *needrender = SDL_TRUE; | |
| updatepreview = SDL_TRUE; | |
| break; | |
| case 0: | |
| return SDL_FALSE; | |
| case 'q': | |
| lastcmd = ARPT_QUIT; | |
| switch( cmd[i+1] ) | |
| { | |
| case 32: | |
| case 0: | |
| case 'm': | |
| mon_store_state( oric ); | |
| setemumode( oric, NULL, EM_RUNNING ); | |
| break; | |
| case 'e': | |
| done = SDL_TRUE; | |
| break; | |
| default: | |
| mon_printf( "???" ); | |
| break; | |
| } | |
| break; | |
| case 'x': | |
| mon_store_state( oric ); | |
| setemumode( oric, NULL, EM_RUNNING ); | |
| break; | |
| case 'f': | |
| lastcmd = 0; | |
| i++; | |
| switch( cmd[i] ) | |
| { | |
| // fd - disassemble to file | |
| case 'd': | |
| i++; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Start address expected\n" ); | |
| break; | |
| } | |
| mon_addr = v; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| { | |
| mon_str( "End address expected\n" ); | |
| break; | |
| } | |
| while( isws( cmd[i] ) ) i++; | |
| if( !cmd[i] ) | |
| { | |
| mon_str( "Filename expected" ); | |
| break; | |
| } | |
| f = fopen( &cmd[i], "w" ); | |
| if( !f ) | |
| { | |
| mon_printf( "Unable to open '%s'", &cmd[i] ); | |
| break; | |
| } | |
| while( mon_addr <= v ) | |
| { | |
| SDL_bool looped; | |
| fprintf( f, "%s\n", mon_disassemble( oric, &mon_addr, &looped, SDL_TRUE ) ); | |
| if( looped ) break; | |
| } | |
| fclose( f ); | |
| break; | |
| // fw - write mem to bin file | |
| case 'w': | |
| i++; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_TRUE, SDL_TRUE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Address expected" ); | |
| break; | |
| } | |
| if( !mon_getnum( oric, &w, cmd, &i, SDL_TRUE, SDL_TRUE, SDL_TRUE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Size expected" ); | |
| break; | |
| } | |
| while( isws( cmd[i] ) ) i++; | |
| if( !cmd[i] ) | |
| { | |
| mon_str( "Filename expected" ); | |
| break; | |
| } | |
| tmem = malloc( w ); | |
| if( !tmem ) | |
| { | |
| mon_str( "Amnesia!" ); | |
| break; | |
| } | |
| for( j=0; j<w; j++ ) | |
| tmem[j] = mon_read( oric, v+j ); | |
| f = fopen( &cmd[i], "wb" ); | |
| if( !f ) | |
| { | |
| free( tmem ); | |
| mon_printf( "Unable to open '%s'", &cmd[i] ); | |
| break; | |
| } | |
| fwrite( tmem, w, 1, f ); | |
| fclose( f ); | |
| free( tmem ); | |
| mon_printf( "Written %d bytes to '%s'", w, &cmd[i] ); | |
| break; | |
| // ToDo: fw - write mem to tap file | |
| // case 't': | |
| // break; | |
| // fr - read file to mem | |
| case 'r': | |
| i++; | |
| if( !mon_getnum( oric, &v, cmd, &i, SDL_TRUE, SDL_TRUE, SDL_TRUE, SDL_TRUE ) ) | |
| { | |
| mon_str( "Address expected" ); | |
| break; | |
| } | |
| while( isws( cmd[i] ) ) i++; | |
| if( !cmd[i] ) | |
| { | |
| mon_str( "Filename expected" ); | |
| break; | |
| } | |
| f = fopen( &cmd[i], "rb" ); | |
| if( !f ) | |
| { | |
| mon_printf( "Unable to open '%s'", &cmd[i] ); | |
| break; | |
| } | |
| mon_set_modified( oric ); | |
| for( j=0; !feof( f ); ) | |
| { | |
| w = fgetc(f); | |
| if( -1 != w ) | |
| { | |
| oric->cpu.write( &oric->cpu, v & 0xffff, w & 0xff ); | |
| v++; | |
| j++; | |
| } | |
| } | |
| fclose( f ); | |
| mon_printf( "%d bytes read from '%s'", j, &cmd[i] ); | |
| updatepreview = SDL_TRUE; | |
| break; | |
| } | |
| break; | |
| case 'n': | |
| lastcmd = 0; | |
| i++; | |
| j = cmd[i]; | |
| switch( j ) | |
| { | |
| case 'l': | |
| case 's': | |
| i++; | |
| while( isws( cmd[i] ) ) i++; | |
| if( !cmd[i] ) | |
| { | |
| mon_str( "Filename expected" ); | |
| break; | |
| } | |
| joinpath(snappath, &cmd[i]); | |
| if (j == 'l') | |
| { | |
| if (!load_snapshot(oric, filetmp)) | |
| mon_printf("Snapshot load failed"); | |
| else | |
| mon_printf("Snapshot loaded"); | |
| } | |
| else | |
| { | |
| if (!save_snapshot(oric, filetmp)) | |
| mon_printf("Snapshot save failed"); | |
| else | |
| mon_printf("Snapshot saved"); | |
| } | |
| break; | |
| default: | |
| mon_printf( "???" ); | |
| break; | |
| } | |
| break; | |
| case '?': | |
| lastcmd = ARPT_HELP; | |
| switch( helpcount ) | |
| { | |
| case 0: | |
| mon_str( "KEYS:" ); | |
| // | - | - | | |
| mon_str( " F2 : Quit Monitor F3 : Toggle Console" ); | |
| mon_str( " F4 : Toggle info F9 : Reset cycles" ); | |
| mon_str( " F10: Step into F11: Step over" ); | |
| mon_str( " F12: Skip inst." ); | |
| mon_str( " " ); | |
| mon_str( "COMMANDS:" ); | |
| mon_str( " a <addr> - Assemble" ); | |
| mon_str( " bc <bp id> - Clear breakpoint" ); | |
| mon_str( " bcm <bp id> - Clear mem breakpoint" ); | |
| mon_str( " bl - List breakpoints" ); | |
| mon_str( " blm - List mem breakpoints" ); | |
| mon_str( " bs <addr> [zc] - Set breakpoint/cycles" ); | |
| mon_str( " bsm <addr> [rwc] - Set mem breakpoint" ); | |
| mon_str( " bz - Zap breakpoints" ); | |
| mon_str( " bzm - Zap mem breakpoints" ); | |
| mon_str( " d <addr> - Disassemble" ); | |
| mon_str( "---- MORE" ); | |
| helpcount++; | |
| break; | |
| case 1: | |
| mon_str( " m <addr> - Dump memory" ); | |
| mon_str( " mm <addr> <value> - Modify memory" ); | |
| mon_str( " mw <addr> - Memory watch at addr" ); | |
| mon_str( " ms <addr> <value> - Memory search" ); | |
| mon_str( " mr <addr> - Memory search refine" ); | |
| mon_str( " mp - Memory print search" ); | |
| mon_str( " nl <filename> - Load snapshot" ); | |
| mon_str( " ns <filename> - Save snapshot" ); | |
| mon_str( " r <reg> <val> - Set <reg> to <val>" ); | |
| mon_str( " q, x or qm - Quit monitor" ); | |
| mon_str( " qe - Quit emulator" ); | |
| mon_str( " sa <name> <addr> - Add or move user sym." ); | |
| mon_str( " sk <name> - Kill user symbol" ); | |
| mon_str( " sc - Symbols not case-sens." ); | |
| mon_str( " sC - Symbols case-sensitive" ); | |
| mon_str( " sl <file> - Load user symbols" ); | |
| mon_str( " sx <file> - Export user symbols" ); | |
| mon_str( " sz - Zap user symbols" ); | |
| mon_str( " " ); | |
| mon_str( "---- MORE" ); | |
| helpcount++; | |
| break; | |
| case 2: | |
| mon_str( " fd <addr> <end> <file>- Disassemble to file" ); | |
| mon_str( " fw <addr> <len> <file>- Write mem to bin file" ); | |
| // ToDo: mon_str( " ft <addr> <len> <file>- Write mem to tap file" ); | |
| mon_str( " fr <addr> <file> - Read bin file to mem" ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| mon_str( " " ); | |
| helpcount = 0; | |
| lastcmd = 0; | |
| break; | |
| } | |
| break; | |
| default: | |
| lastcmd = 0; | |
| mon_printf( "???" ); | |
| break; | |
| } | |
| return done; | |
| } | |
| SDL_bool mon_do_cmd( char *cmd, struct machine *oric, SDL_bool *needrender ) | |
| { | |
| int i; | |
| SDL_bool ret; | |
| mon_hide_curs(); | |
| for(i=2; i<49; i++) tz[TZ_MONITOR]->tx[50*19+i] = 32; | |
| tzstrpos( tz[TZ_MONITOR], 2, 19, cmd ); | |
| tzsetcol( tz[TZ_MONITOR], 2, 3 ); | |
| ret = mon_cmd( cmd, oric, needrender ); | |
| mon_start_input(); | |
| mon_show_curs(); | |
| return ret; | |
| } | |
| static void mon_write_ibuf( void ) | |
| { | |
| char ibtmp[CONS_WIDTH+1]; | |
| strncpy( ibtmp, &ibuf[iloff], CONS_WIDTH ); | |
| ibtmp[CONS_WIDTH] = 0; | |
| tzstrpos( tz[TZ_MONITOR], 1, 19, iloff > 0 ? "\x16" : "]" ); | |
| tzstrpos( tz[TZ_MONITOR], 2, 19, ibtmp ); | |
| if( strlen( &ibuf[iloff] ) > CONS_WIDTH ) | |
| { | |
| tzstrpos( tz[TZ_MONITOR], 2+CONS_WIDTH, 19, "\x16" ); | |
| } else { | |
| tzstr( tz[TZ_MONITOR], " " ); | |
| tzstrpos( tz[TZ_MONITOR], 2+CONS_WIDTH, 19, " " ); | |
| } | |
| } | |
| static void mon_write_ibuf_asm( void ) | |
| { | |
| char ibtmp[CONS_WIDTH+1]; | |
| strncpy( ibtmp, ibuf, CONS_WIDTH ); | |
| ibtmp[CONS_WIDTH] = 0; | |
| tzstrpos( tz[TZ_MONITOR], 8, 19, ibtmp ); | |
| tzstr( tz[TZ_MONITOR], " " ); | |
| } | |
| static void mon_set_curs_to_end( void ) | |
| { | |
| cursx = ilen; | |
| iloff = ilen-CONS_WIDTH; | |
| if( iloff < 0 ) iloff = 0; | |
| } | |
| static void mon_set_iloff( void ) | |
| { | |
| if( cursx < iloff ) iloff = cursx; | |
| if( cursx >= (iloff+CONS_WIDTH) ) iloff = cursx-CONS_WIDTH; | |
| if( iloff < 0 ) iloff =0; | |
| } | |
| /* | |
| - AM_IMP=0, | |
| - AM_IMM, | |
| AM_ZP, <-- AM_ABS | |
| AM_ZPX, <-- AM_ABX | |
| AM_ZPY, <-- AM_ABY | |
| AM_ABS, nnnn | |
| AM_ABX, nnnn,x | |
| AM_ABY, nnnn,y | |
| - AM_ZIX, (nn,x) | |
| - AM_ZIY, (nn),y | |
| AM_REL, <-- AM_ABS | |
| - AM_IND (nnnn) | |
| */ | |
| static SDL_bool mon_decodeoperand( struct machine *oric, char *ptr, int *type, unsigned short *val ) | |
| { | |
| int i; | |
| unsigned int v; | |
| i=0; | |
| while( isws( ptr[i] ) ) i++; | |
| // Implied | |
| if( ptr[i] == 0 ) | |
| { | |
| (*type) = AM_IMP; | |
| return SDL_TRUE; | |
| } | |
| // Immediate | |
| if( ptr[i] == '#' ) | |
| { | |
| i++; | |
| if( !mon_getnum( oric, &v, ptr, &i, SDL_FALSE, SDL_FALSE, SDL_FALSE, SDL_TRUE ) ) | |
| return SDL_FALSE; | |
| (*type) = AM_IMM; | |
| (*val) = v; | |
| return SDL_TRUE; | |
| } | |
| // ZIX, ZIY, IND | |
| if( ptr[i] == '(' ) | |
| { | |
| i++; | |
| if( !mon_getnum( oric, &v, ptr, &i, SDL_TRUE, SDL_TRUE, SDL_FALSE, SDL_TRUE ) ) | |
| return SDL_FALSE; | |
| if( strncasecmp( &ptr[i], ",X)", 3 ) == 0 ) | |
| { | |
| (*type) = AM_ZIX; | |
| (*val) = v&0xff; | |
| return SDL_TRUE; | |
| } | |
| if( strncasecmp( &ptr[i], "),Y", 3 ) == 0 ) | |
| { | |
| (*type) = AM_ZIY; | |
| (*val) = v&0xff; | |
| return SDL_TRUE; | |
| } | |
| if( ptr[i] == ')' ) | |
| { | |
| (*type) = AM_IND; | |
| (*val) = v; | |
| return SDL_TRUE; | |
| } | |
| return SDL_FALSE; | |
| } | |
| if( !mon_getnum( oric, &v, ptr, &i, SDL_TRUE, SDL_TRUE, SDL_FALSE, SDL_TRUE ) ) | |
| return SDL_FALSE; | |
| if( strncasecmp( &ptr[i], ",X", 2 ) == 0 ) | |
| { | |
| (*type) = AM_ABX; | |
| (*val) = v; | |
| return SDL_TRUE; | |
| } | |
| if( strncasecmp( &ptr[i], ",Y", 2 ) == 0 ) | |
| { | |
| (*type) = AM_ABY; | |
| (*val) = v; | |
| return SDL_TRUE; | |
| } | |
| (*type) = AM_ABS; | |
| (*val) = v; | |
| return SDL_TRUE; | |
| } | |
| static SDL_bool mon_assemble_line( struct machine *oric ) | |
| { | |
| int i, j, addsym, amode; | |
| unsigned short val; | |
| i=0; | |
| while( isws( ibuf[i] ) ) i++; | |
| if( ibuf[i] == 0 ) return SDL_TRUE; | |
| // Starts with a label? | |
| j = i; | |
| addsym = -1; | |
| if( issymstart( ibuf[j] ) ) | |
| { | |
| while( issymchar( ibuf[j] ) ) j++; | |
| if( ibuf[j] == ':' ) | |
| { | |
| addsym = i; | |
| i = j+1; | |
| while( isws( ibuf[i] ) ) i++; | |
| } | |
| } | |
| for( j=0; asmtab[j].name; j++ ) | |
| { | |
| if( strncasecmp( asmtab[j].name, &ibuf[i], 3 ) == 0 ) | |
| break; | |
| } | |
| if( !asmtab[j].name ) | |
| { | |
| mon_oprintf( " %04X %c%c%c ??? ", mon_addr, ibuf[i], ibuf[i+1], ibuf[i+2] ); | |
| return SDL_FALSE; | |
| } | |
| i += 3; | |
| if( !mon_decodeoperand( oric, &ibuf[i], &amode, &val ) ) | |
| { | |
| mon_str( "Illegal operand" ); | |
| return SDL_FALSE; | |
| } | |
| switch( amode ) | |
| { | |
| case AM_IMP: | |
| if( asmtab[j].imp == -1 ) { mon_str( "Operand expected" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].imp ); | |
| break; | |
| case AM_IMM: | |
| if( asmtab[j].imm == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].imm ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| case AM_ABS: | |
| if( asmtab[j].rel != -1 ) | |
| { | |
| i = ((int)val)-((int)(mon_addr+2)); | |
| if( ( i < -128 ) || ( i > 127 ) ) | |
| { | |
| mon_str( "Branch out of range" ); | |
| return SDL_FALSE; | |
| } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].rel ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, i&0xff ); | |
| break; | |
| } | |
| if( ( asmtab[j].zp != -1 ) && ( (val&0xff00)==0 ) ) | |
| { | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].zp ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| } | |
| if( asmtab[j].abs == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].abs ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val&0xff ); | |
| oric->cpu.write( &oric->cpu, mon_addr+2, (val>>8)&0xff ); | |
| break; | |
| case AM_IND: | |
| if( asmtab[j].ind == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].ind ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val&0xff ); | |
| oric->cpu.write( &oric->cpu, mon_addr+2, (val>>8)&0xff ); | |
| break; | |
| case AM_ZPX: | |
| if( asmtab[j].zpx == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].zpx ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| case AM_ZPY: | |
| if( asmtab[j].zpy == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].zpy ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| case AM_ZIX: | |
| if( asmtab[j].zix == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].zix ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| case AM_ZIY: | |
| if( asmtab[j].ziy == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].ziy ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| case AM_ABX: | |
| if( ( asmtab[j].zpx != -1 ) && ( (val&0xff00)==0 ) ) | |
| { | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].zpx ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| } | |
| if( asmtab[j].abx == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].abx ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val&0xff ); | |
| oric->cpu.write( &oric->cpu, mon_addr+2, (val>>8)&0xff ); | |
| break; | |
| case AM_ABY: | |
| if( ( asmtab[j].zpy != -1 ) && ( (val&0xff00)==0 ) ) | |
| { | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].zpy ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val ); | |
| break; | |
| } | |
| if( asmtab[j].aby == -1 ) { mon_str( "Illegal operand" ); return SDL_FALSE; } | |
| mon_set_modified( oric ); | |
| oric->cpu.write( &oric->cpu, mon_addr, asmtab[j].aby ); | |
| oric->cpu.write( &oric->cpu, mon_addr+1, val&0xff ); | |
| oric->cpu.write( &oric->cpu, mon_addr+2, (val>>8)&0xff ); | |
| break; | |
| } | |
| if( addsym != -1 ) | |
| mon_replace_or_add_symbol( &oric->usersyms, oric, &ibuf[addsym], SYM_BESTGUESS, mon_addr ); | |
| mon_oprintf( mon_disassemble( oric, &mon_addr, NULL, SDL_FALSE ) ); | |
| return SDL_FALSE; | |
| } | |
| static SDL_bool mon_console_keydown( SDL_Event *ev, struct machine *oric, SDL_bool *needrender ) | |
| { | |
| int i; | |
| SDL_bool done; | |
| done = SDL_FALSE; | |
| if( mon_asmmode ) | |
| { | |
| switch( ev->key.keysym.sym ) | |
| { | |
| case SDLK_LEFT: | |
| if( cursx > 0 ) | |
| { | |
| mon_hide_curs(); | |
| cursx--; | |
| mon_write_ibuf_asm(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| case SDLK_RIGHT: | |
| if( cursx < ilen ) | |
| { | |
| mon_hide_curs(); | |
| cursx++; | |
| mon_write_ibuf_asm(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| case SDLK_BACKSPACE: | |
| if( cursx > 0 ) | |
| { | |
| mon_hide_curs(); | |
| for( i=cursx-1; i<ilen; i++ ) | |
| ibuf[i] = ibuf[i+1]; | |
| cursx--; | |
| ilen = (int)strlen( ibuf ); | |
| mon_set_iloff(); | |
| mon_write_ibuf_asm(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| case SDLK_RETURN: | |
| case SDLK_KP_ENTER: | |
| mon_hide_curs(); | |
| ibuf[ilen] = 0; | |
| if( mon_assemble_line( oric ) ) | |
| { | |
| mon_asmmode = SDL_FALSE; | |
| mon_start_input(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| updatepreview = SDL_TRUE; | |
| break; | |
| } | |
| mon_start_input(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| updatepreview = SDL_TRUE; | |
| break; | |
| default: | |
| break; | |
| } | |
| switch( SDL_COMPAT_GetKeysymUnicode( ev->key.keysym ) ) | |
| { | |
| default: | |
| if( ( SDL_COMPAT_GetKeysymUnicode( ev->key.keysym ) > 31 ) && ( SDL_COMPAT_GetKeysymUnicode( ev->key.keysym ) < 127 ) ) | |
| { | |
| if( ilen >= MAX_ASM_INPUT ) break; | |
| mon_hide_curs(); | |
| for( i=ilen+1; i>cursx; i-- ) | |
| ibuf[i] = ibuf[i-1]; | |
| ibuf[cursx] = SDL_COMPAT_TranslateUnicode( ev->key.keysym ); | |
| cursx++; | |
| ilen++; | |
| mon_write_ibuf_asm(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| } | |
| return done; | |
| } | |
| switch( ev->key.keysym.sym ) | |
| { | |
| case SDLK_UP: | |
| if( histp >= (histu-1) ) break; | |
| mon_hide_curs(); | |
| strcpy( ibuf, &history[++histp][0] ); | |
| ilen = (int)strlen( ibuf ); | |
| mon_set_curs_to_end(); | |
| mon_set_iloff(); | |
| tzstrpos( tz[TZ_MONITOR], 2, 19, " " ); | |
| mon_write_ibuf(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_DOWN: | |
| mon_hide_curs(); | |
| if( histp <= 0 ) | |
| { | |
| histp = -1; | |
| ibuf[0] = 0; | |
| ilen = 0; | |
| iloff = 0; | |
| cursx = 0; | |
| } else { | |
| strcpy( ibuf, &history[--histp][0] ); | |
| mon_set_curs_to_end(); | |
| mon_set_iloff(); | |
| } | |
| tzstrpos( tz[TZ_MONITOR], 2, 19, " " ); | |
| mon_write_ibuf(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_LEFT: | |
| if( cursx > 0 ) | |
| { | |
| mon_hide_curs(); | |
| cursx--; | |
| mon_set_iloff(); | |
| mon_write_ibuf(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| case SDLK_RIGHT: | |
| if( cursx < ilen ) | |
| { | |
| mon_hide_curs(); | |
| cursx++; | |
| mon_set_iloff(); | |
| mon_write_ibuf(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| default: | |
| break; | |
| case SDLK_BACKSPACE: | |
| if( cursx > 0 ) | |
| { | |
| mon_hide_curs(); | |
| for( i=cursx-1; i<ilen; i++ ) | |
| ibuf[i] = ibuf[i+1]; | |
| cursx--; | |
| ilen = (int)strlen( ibuf ); | |
| mon_set_iloff(); | |
| mon_write_ibuf(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| case SDLK_RETURN: | |
| case SDLK_KP_ENTER: | |
| mon_hide_curs(); | |
| ibuf[ilen] = 0; | |
| if( 0 == ilen && 0 != lastcmd ) | |
| { | |
| switch( lastcmd ) | |
| { | |
| case ARPT_HELP: // '?' | |
| case ARPT_MEMORY: // 'm' | |
| case ARPT_DISASM: // 'd' | |
| case ARPT_ASSEM: // 'a' | |
| case ARPT_QUIT: // 'q', | |
| ibuf[cursx++] = lastcmd; | |
| ibuf[cursx] = 0; | |
| ilen = 1; | |
| break; | |
| case ARPT_SEARCH: // 'mp' | |
| ibuf[cursx++] = 'm'; | |
| ibuf[cursx++] = 'p'; | |
| ibuf[cursx] = 0; | |
| ilen = 2; | |
| break; | |
| default: | |
| lastcmd = 0; | |
| ilen = 0; | |
| break; | |
| } | |
| } | |
| else if ( 0 < ilen ) | |
| { | |
| if( !( ( histu > 0 ) && ( strcmp( &history[0][0], ibuf ) == 0 ) ) ) | |
| { | |
| if( histu > 0 ) | |
| { | |
| for( i=histu; i>0; i-- ) | |
| strcpy( &history[i][0], &history[i-1][0] ); | |
| } | |
| strcpy( &history[0][0], ibuf ); | |
| if( histu < 10 ) histu++; | |
| } | |
| } | |
| histp = -1; | |
| tzsetcol( tz[TZ_MONITOR], 2, 3 ); | |
| done |= mon_cmd( ibuf, oric, needrender ); | |
| mon_start_input(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| break; | |
| } | |
| switch( SDL_COMPAT_GetKeysymUnicode( ev->key.keysym ) ) | |
| { | |
| default: | |
| if( ( SDL_COMPAT_GetKeysymUnicode( ev->key.keysym ) > 31 ) && ( SDL_COMPAT_GetKeysymUnicode( ev->key.keysym ) < 127 ) ) | |
| { | |
| if( ilen >= MAX_CONS_INPUT ) break; | |
| mon_hide_curs(); | |
| for( i=ilen+1; i>cursx; i-- ) | |
| ibuf[i] = ibuf[i-1]; | |
| ibuf[cursx] = SDL_COMPAT_TranslateUnicode( ev->key.keysym ); | |
| cursx++; | |
| ilen++; | |
| mon_set_iloff(); | |
| mon_write_ibuf(); | |
| mon_show_curs(); | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| } | |
| return done; | |
| } | |
| static SDL_bool mon_mwatch_keydown( SDL_Event *ev, struct machine *oric, SDL_bool *needrender ) | |
| { | |
| SDL_bool done; | |
| unsigned int v; | |
| int i, page; | |
| page = mw_split ? 8*8 : 8*18; | |
| done = SDL_FALSE; | |
| switch( ev->key.keysym.sym ) | |
| { | |
| case SDLK_UP: | |
| mw_addr[mw_which] -= kshifted ? page : 8; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_DOWN: | |
| mw_addr[mw_which] += kshifted ? page : 8; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_PAGEUP: | |
| mw_addr[mw_which] -= page; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_PAGEDOWN: | |
| mw_addr[mw_which] += page; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_RETURN: | |
| case SDLK_KP_ENTER: | |
| if( mw_mode != 1 ) break; | |
| mw_ibuf[5] = 0; | |
| mw_mode = 0; | |
| i = 0; | |
| if( mon_getnum( oric, &v, mw_ibuf, &i, SDL_FALSE, SDL_FALSE, SDL_FALSE, SDL_FALSE ) ) | |
| mw_addr[mw_which] = v; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_ESCAPE: | |
| mw_mode = 0; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_BACKSPACE: | |
| if( mw_mode != 1 ) break; | |
| if( mw_koffs <= 0 ) break; | |
| mw_ibuf[mw_koffs--] = 0; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_s: | |
| if( mw_mode != 0 ) break; | |
| mw_split = !mw_split; | |
| if( ( !mw_split ) && ( mw_which != 0 ) ) | |
| mw_which = 0; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_TAB: | |
| if( !mw_split ) break; | |
| if( mw_mode != 0 ) mw_mode = 0; | |
| mw_which ^= 1; | |
| *needrender = SDL_TRUE; | |
| break; | |
| default: | |
| break; | |
| } | |
| if( ishex( SDL_COMPAT_GetKeysymUnicode( ev->key.keysym ) ) ) | |
| { | |
| if( mw_mode != 1 ) | |
| { | |
| mw_mode = 1; | |
| mw_ibuf[0] = '$'; | |
| mw_ibuf[1] = 0; | |
| mw_koffs = 0; | |
| } | |
| if( mw_koffs < 4 ) | |
| { | |
| mw_ibuf[++mw_koffs] = SDL_COMPAT_TranslateUnicode( ev->key.keysym ); | |
| mw_ibuf[mw_koffs+1] = 0; | |
| } | |
| *needrender = SDL_TRUE; | |
| } | |
| return done; | |
| } | |
| static unsigned int steppy_step( struct machine *oric ) | |
| { | |
| m6502_set_icycles( &oric->cpu, SDL_FALSE, mon_bpmsg ); | |
| tape_patches( oric ); | |
| via_clock( &oric->via, oric->cpu.icycles ); | |
| ay_ticktock( &oric->ay, oric->cpu.icycles ); | |
| if((oric->drivetype == DRV_MICRODISC) || (oric->drivetype == DRV_JASMIN)) wd17xx_ticktock( &oric->wddisk, oric->cpu.icycles ); | |
| if( oric->type == MACH_TELESTRAT ) | |
| { | |
| via_clock( &oric->tele_via, oric->cpu.icycles ); | |
| } | |
| if( oric->aciabackend ) | |
| acia_clock( &oric->tele_acia, oric->cpu.icycles ); | |
| oric->cpu.rastercycles -= oric->cpu.icycles; | |
| m6502_inst( &oric->cpu ); | |
| if( oric->cpu.rastercycles <= 0 ) | |
| { | |
| ula_doraster( oric ); | |
| oric->cpu.rastercycles += oric->cyclesperraster; | |
| } | |
| if( mon_bpmsg[0] ) | |
| { | |
| mon_printf_above( mon_bpmsg ); | |
| mon_bpmsg[0] = 0; | |
| } | |
| return oric->cpu.icycles; | |
| } | |
| static SDL_bool clickzone( struct textzone *tz_, int *tx, int *ty, SDL_bool *dblclk ) | |
| { | |
| int dx, dy; | |
| if( !in_textzone( tz_, leftclick[0].x, leftclick[0].y ) ) | |
| return SDL_FALSE; | |
| *tx = (leftclick[0].x - tz_->x) / 8; | |
| *ty = (leftclick[0].y - tz_->y) / 12; | |
| dx = (leftclick[1].x - tz_->x) / 8; | |
| dy = (leftclick[1].y - tz_->y) / 12; | |
| if( ( (*tx) == dx ) && ( (*ty) == dy ) && ( (leftclick[0].time-leftclick[1].time) < 1000 ) ) | |
| { | |
| *dblclk = SDL_TRUE; | |
| // Reset double click timing after a successful double click | |
| leftclick[0].time = -1; | |
| } else { | |
| *dblclk = SDL_FALSE; | |
| } | |
| return SDL_TRUE; | |
| } | |
| SDL_bool mon_event( SDL_Event *ev, struct machine *oric, SDL_bool *needrender ) | |
| { | |
| SDL_bool done; | |
| SDL_bool donkey; | |
| done = SDL_FALSE; | |
| donkey = SDL_FALSE; | |
| switch( ev->type ) | |
| { | |
| case SDL_COMPAT_ACTIVEEVENT: | |
| if(SDL_COMPAT_IsAppFocused(ev)) { | |
| *needrender = SDL_TRUE; | |
| } | |
| break; | |
| case SDL_MOUSEBUTTONDOWN: | |
| { | |
| int tx, ty; | |
| SDL_bool dblclk; | |
| leftclick[1] = leftclick[0]; | |
| leftclick[0].x = ev->button.x; | |
| leftclick[0].y = ev->button.y; | |
| leftclick[0].time = SDL_GetTicks(); | |
| if( clickzone( tz[TZ_REGS], &tx, &ty, &dblclk ) ) | |
| { | |
| mon_click_regs( oric, needrender, tx, ty, dblclk ); | |
| } | |
| } | |
| break; | |
| case SDL_KEYUP: | |
| switch( ev->key.keysym.sym ) | |
| { | |
| case SDLK_F9: | |
| oric->cpu.cycles = 0; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_LSHIFT: | |
| case SDLK_RSHIFT: | |
| kshifted = SDL_FALSE; | |
| break; | |
| case SDLK_F1: | |
| refreshstatus = SDL_TRUE; | |
| *needrender = SDL_TRUE; | |
| mon_store_state( oric ); | |
| ula_set_dirty( oric ); | |
| setemumode( oric, NULL, EM_MENU ); | |
| break; | |
| case SDLK_F2: | |
| // In case we're on a breakpoint | |
| m6502_set_icycles( &oric->cpu, SDL_FALSE, mon_bpmsg ); | |
| tape_patches( oric ); | |
| via_clock( &oric->via, oric->cpu.icycles ); | |
| ay_ticktock( &oric->ay, oric->cpu.icycles ); | |
| if((oric->drivetype == DRV_MICRODISC) || (oric->drivetype == DRV_JASMIN)) wd17xx_ticktock( &oric->wddisk, oric->cpu.icycles ); | |
| if( oric->type == MACH_TELESTRAT ) | |
| { | |
| via_clock( &oric->tele_via, oric->cpu.icycles ); | |
| } | |
| if( oric->aciabackend ) | |
| acia_clock( &oric->tele_acia, oric->cpu.icycles ); | |
| oric->cpu.rastercycles -= oric->cpu.icycles; | |
| m6502_inst( &oric->cpu ); | |
| if( oric->cpu.rastercycles <= 0 ) | |
| { | |
| ula_doraster( oric ); | |
| oric->cpu.rastercycles += oric->cyclesperraster; | |
| } | |
| *needrender = SDL_TRUE; | |
| mon_store_state( oric ); | |
| setemumode( oric, NULL, EM_RUNNING ); | |
| break; | |
| case SDLK_F3: | |
| cshow = (cshow+1)%CSHOW_LAST; | |
| *needrender = SDL_TRUE; | |
| break; | |
| case SDLK_F4: | |
| mshow = (mshow+1)%MSHOW_LAST; | |
| if( ( mshow == MSHOW_VIA2 ) && ( oric->type != MACH_TELESTRAT ) ) | |
| mshow = (mshow+1)%MSHOW_LAST; | |
| if( ( oric->drivetype == DRV_NONE ) && ( mshow == MSHOW_DISK ) ) | |
| mshow = (mshow+1)%MSHOW_LAST; | |
| *needrender = SDL_TRUE; | |
| break; | |
| default: | |
| break; | |
| } | |
| break; | |
| case SDL_KEYDOWN: | |
| switch( ev->key.keysym.sym ) | |
| { | |
| case SDLK_LSHIFT: | |
| case SDLK_RSHIFT: | |
| kshifted = SDL_TRUE; | |
| donkey = SDL_TRUE; | |
| break; | |
| case SDLK_F10: | |
| if( !kshifted ) | |
| { | |
| mon_store_state( oric ); | |
| steppy_step( oric ); | |
| *needrender = SDL_TRUE; | |
| donkey = SDL_TRUE; | |
| break; | |
| } | |
| case SDLK_F11: | |
| if( mon_read( oric, oric->cpu.pc ) == 0x20 ) // JSR instruction? | |
| { | |
| Uint16 newpc; | |
| unsigned int endticks; | |
| newpc = oric->cpu.pc+3; | |
| mon_store_state( oric ); | |
| endticks = SDL_GetTicks()+5000; // 5 seconds to comply | |
| while( ( oric->cpu.pc != newpc ) && ( SDL_GetTicks() < endticks ) ) | |
| steppy_step( oric ); | |
| *needrender = SDL_TRUE; | |
| donkey = SDL_TRUE; | |
| break; | |
| } | |
| mon_store_state( oric ); | |
| steppy_step( oric ); | |
| *needrender = SDL_TRUE; | |
| donkey = SDL_TRUE; | |
| break; | |
| case SDLK_F12: | |
| switch( distab[mon_read( oric, oric->cpu.pc )].amode ) | |
| { | |
| case AM_IMM: | |
| case AM_ZP: | |
| case AM_ZPX: | |
| case AM_ZPY: | |
| case AM_ZIX: | |
| case AM_ZIY: | |
| case AM_REL: | |
| oric->cpu.pc += 2; | |
| break; | |
| case AM_ABS: | |
| case AM_ABX: | |
| case AM_ABY: | |
| case AM_IND: | |
| oric->cpu.pc += 3; | |
| break; | |
| case AM_IMP: | |
| default: | |
| oric->cpu.pc++; | |
| break; | |
| } | |
| *needrender = SDL_TRUE; | |
| donkey = SDL_TRUE; | |
| break; | |
| default: | |
| break; | |
| } | |
| if( !donkey ) | |
| { | |
| switch( cshow ) | |
| { | |
| case CSHOW_CONSOLE: | |
| done |= mon_console_keydown( ev, oric, needrender ); | |
| break; | |
| case CSHOW_MWATCH: | |
| done |= mon_mwatch_keydown( ev, oric, needrender ); | |
| break; | |
| } | |
| } | |
| break; | |
| } | |
| return done; | |
| } | |
| #if defined(DEBUG_CPU_TRACE) && DEBUG_CPU_TRACE > 0 | |
| struct cpu_trace_entry cputrace[DEBUG_CPU_TRACE], *list_start = NULL, *list_end, *next = NULL; | |
| void mon_traceinst(struct m6502 *cpu) | |
| { | |
| struct machine *oric = (struct machine *)cpu->userdata; | |
| if (!list_start) | |
| { | |
| int i; | |
| list_start = &cputrace[0]; | |
| list_end = &cputrace[DEBUG_CPU_TRACE-1]; | |
| for (i=0; i<DEBUG_CPU_TRACE; i++) | |
| { | |
| cputrace[i].prev = (i==0) ? NULL : &cputrace[i-1]; | |
| cputrace[i].next = (i==(DEBUG_CPU_TRACE-1)) ? NULL : &cputrace[i+1]; | |
| } | |
| next = list_start; | |
| } | |
| /* Quicker than shuffling an array... */ | |
| if (next == NULL) | |
| { | |
| next = list_start; | |
| list_start = list_start->next; | |
| list_end->next = next; | |
| next->prev = list_end; | |
| next->next = NULL; | |
| list_start->prev = NULL; | |
| list_end = next; | |
| } | |
| next->pc = cpu->calcpc; | |
| next->a = cpu->a; | |
| next->x = cpu->x; | |
| next->y = cpu->y; | |
| next->sp = cpu->sp; | |
| next->flags = MAKEFLAGS; | |
| next->inst[0] = mon_read(oric, cpu->calcpc); | |
| next->inst[1] = mon_read(oric, cpu->calcpc+1); | |
| next->inst[2] = mon_read(oric, cpu->calcpc+2); | |
| next->romdis = oric->romdis; | |
| if( ( oric->drivetype == DRV_JASMIN ) && ( oric->jasmin.olay ) ) | |
| next->romdis = SDL_FALSE; | |
| next = next->next; | |
| } | |
| char *cputrace_print( struct machine *oric, struct cpu_trace_entry *cte ) | |
| { | |
| unsigned short iaddr, addr; | |
| unsigned char op, a1, a2; | |
| int i; | |
| char *tmpsname, *disptr; | |
| char sname[SNAME_LEN+1]; | |
| struct msym *csym; | |
| disptr = distmp; | |
| tmpsname = ""; | |
| csym = mon_find_sym_by_addr( oric, cte->pc, &cte->romdis ); | |
| if( csym ) | |
| { | |
| tmpsname = csym->name; | |
| if( strlen( tmpsname ) > SNAME_LEN ) | |
| { | |
| sprintf( distmp, "%s\n", tmpsname ); | |
| disptr = &distmp[strlen(distmp)]; | |
| tmpsname = ""; | |
| } | |
| } | |
| strcpy( sname, tmpsname ); | |
| for( i=strlen(sname); i<SNAME_LEN; i++ ) | |
| sname[i] = 32; | |
| sname[i] = 0; | |
| iaddr = cte->pc; | |
| op = cte->inst[0]; | |
| a1 = cte->inst[1]; | |
| a2 = cte->inst[2]; | |
| switch( distab[op].amode ) | |
| { | |
| case AM_IMP: | |
| sprintf( disptr, "%s %04X %02X %s", sname, iaddr, op, distab[op].name ); | |
| break; | |
| case AM_IMM: | |
| sprintf( disptr, "%s %04X %02X %02X %s #$%02X", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| break; | |
| case AM_ZP: | |
| case AM_ZPX: | |
| case AM_ZPY: | |
| csym = mon_find_sym_by_addr( oric, a1, &cte->romdis ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s %s", sname, iaddr, op, a1, distab[op].name, csym->name ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s $%02X", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| if( distab[op].amode == AM_ZP ) break; | |
| strcat( disptr, distab[op].amode == AM_ZPX ? ",X" : ",Y" ); | |
| break; | |
| case AM_ABS: | |
| case AM_ABX: | |
| case AM_ABY: | |
| csym = mon_find_sym_by_addr( oric, (a2<<8)|a1, &cte->romdis ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s %s", sname, iaddr, op, a1, a2, distab[op].name, csym->name ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s $%02X%02X", sname, iaddr, op, a1, a2, distab[op].name, a2, a1 ); | |
| if( distab[op].amode == AM_ABS ) break; | |
| strcat( disptr, distab[op].amode == AM_ABX ? ",X" : ",Y" ); | |
| break; | |
| case AM_ZIX: | |
| csym = mon_find_sym_by_addr( oric, a1, &cte->romdis ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s (%s,X)", sname, iaddr, op, a1, distab[op].name, csym->name ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s ($%02X,X)", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| break; | |
| case AM_ZIY: | |
| csym = mon_find_sym_by_addr( oric, a1, &cte->romdis ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s (%s),Y", sname, iaddr, op, a1, distab[op].name, csym->name ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s ($%02X),Y", sname, iaddr, op, a1, distab[op].name, a1 ); | |
| break; | |
| case AM_REL: | |
| addr = ((cte->pc+2)+((signed char)a1))&0xffff; | |
| csym = mon_find_sym_by_addr( oric, addr, &cte->romdis ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %s %s", sname, iaddr, op, a1, distab[op].name, csym->name ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %s $%04X", sname, iaddr, op, a1, distab[op].name, addr ); | |
| break; | |
| case AM_IND: | |
| csym = mon_find_sym_by_addr( oric, (a2<<8)|a1, &cte->romdis ); | |
| if( csym ) | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s (%s)", sname, iaddr, op, a1, a2, distab[op].name, csym->name ); | |
| else | |
| sprintf( disptr, "%s %04X %02X %02X %02X %s ($%02X%02X)", sname, iaddr, op, a1, a2, distab[op].name, a2, a1 ); | |
| break; | |
| default: | |
| strcpy( disptr, " WTF?" ); | |
| break; | |
| } | |
| for( i=strlen(disptr); i<60; i++ ) | |
| disptr[i] = 32; | |
| disptr[i] = 0; | |
| sprintf(&disptr[60], "%c%c-%c%c%c%c%c A=%02X X=%02X Y=%02X SP=%04X ROMDIS=%d", | |
| (cte->flags&0x80) ? 'N' : '-', | |
| (cte->flags&0x40) ? 'V' : '-', | |
| (cte->flags&0x10) ? 'B' : '-', | |
| (cte->flags&0x08) ? 'D' : '-', | |
| (cte->flags&0x04) ? 'I' : '-', | |
| (cte->flags&0x02) ? 'Z' : '-', | |
| (cte->flags&0x01) ? 'C' : '-', | |
| cte->a, | |
| cte->x, | |
| cte->y, | |
| cte->sp+0x100, | |
| cte->romdis); | |
| return distmp; | |
| } | |
| void dump_cputrace(struct machine *oric) | |
| { | |
| struct cpu_trace_entry *iter = list_start; | |
| while (iter != next) | |
| { | |
| printf("%s\n", cputrace_print(oric, iter)); | |
| iter = iter->next; | |
| } | |
| } | |
| #endif |