diff options
author | Ian C <ianc@noddybox.co.uk> | 2006-08-30 22:24:41 +0000 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2006-08-30 22:24:41 +0000 |
commit | c1d4cc4739583f906b639daf3bd9384dd791530e (patch) | |
tree | 27f471459ec61067210883ff21396d0bc14a7fdc | |
parent | cb4cd60cbce11439b0e0529df20e671e5b49b6f1 (diff) |
Development checkin
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | callbacks.c | 74 | ||||
-rw-r--r-- | callbacks.h | 40 | ||||
-rw-r--r-- | gemma.c | 837 | ||||
-rw-r--r-- | gemma.glade | 420 | ||||
-rw-r--r-- | gemma.h | 56 | ||||
-rw-r--r-- | gtkutil.c | 21 | ||||
-rw-r--r-- | gtkutil.h | 4 | ||||
-rw-r--r-- | main.c | 28 | ||||
-rw-r--r-- | z80.c | 6 | ||||
-rw-r--r-- | z80.h | 5 |
11 files changed, 1309 insertions, 192 deletions
@@ -18,7 +18,7 @@ # # ------------------------------------------------------------------------- # -# $Id: Makefile,v 1.12 2006-08-28 22:40:44 ianc Exp $ +# $Id: Makefile,v 1.13 2006-08-30 22:24:41 ianc Exp $ # # @@ -70,7 +70,8 @@ SOURCE = z80.c \ support.c \ callbacks.c \ interface.c \ - gtkutil.c + gtkutil.c \ + gemma.c BASE_O = z80.o \ z80_decode.o \ @@ -83,7 +84,8 @@ GEMMA_O = main.o \ support.o \ callbacks.o \ interface.o \ - gtkutil.o + gtkutil.o \ + gemma.o all: $(TARGETS) @@ -91,7 +93,7 @@ emma: $(BASE_O) $(EMMA_O) cc -o emma $(BASE_O) $(EMMA_O) $(LIBS) gemma: $(BASE_O) $(GEMMA_O) - cc -o gemma $(GBASE_O) $(GEMMA_O) `pkg-config --libs gtk+-2.0` + cc -o gemma $(BASE_O) $(GEMMA_O) `pkg-config --libs gtk+-2.0` tests: emucpm.hex zexdoc.hex zexall.hex diff --git a/callbacks.c b/callbacks.c index 019fde9..a0a7a1a 100644 --- a/callbacks.c +++ b/callbacks.c @@ -3,8 +3,82 @@ #endif #include <gtk/gtk.h> +#include <limits.h> #include "callbacks.h" #include "interface.h" #include "support.h" +#include "gtkutil.h" +#include "gemma.h" + + +void CloseApplication(GtkObject *object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void OnRun(GtkButton *button, gpointer user_data) +{ + GEMMA_Run(); +} + + +void OnStep(GtkButton *button, gpointer user_data) +{ + GEMMA_Step(); +} + + +void OnStepOver(GtkButton *button, gpointer user_data) +{ + GEMMA_StepOver(); +} + + +void OnStop(GtkButton *button, gpointer user_data) +{ + GEMMA_Stop(); +} + + +void OnLoadHEX(GtkButton *button, gpointer user_data) +{ + static char path[PATH_MAX]={0}; + + if (DialogFSelect("Select INTEL HEX File to load",path)) + { + GEMMA_LoadHEX(path); + } +} + + +void OnLoadLabels(GtkButton *button, gpointer user_data) +{ + static char path[PATH_MAX]={0}; + + if (DialogFSelect("Select Label File to load",path)) + { + GEMMA_LoadLabels(path); + } +} + + +void OnRunUntil(GtkButton *button, gpointer user_data) +{ + DialogOK("Not yet implemented"); +} + + +void OnQuit(GtkButton *button, gpointer user_data) +{ + gtk_main_quit(); +} + + +void OnMemoryViewChoice(GtkComboBox *combobox, gpointer user_data) +{ + GEMMA_UpdateDisplay(UPDATE_MEM_VIEW); +} + diff --git a/callbacks.h b/callbacks.h index 6fefc7c..f3a05f5 100644 --- a/callbacks.h +++ b/callbacks.h @@ -1,2 +1,42 @@ #include <gtk/gtk.h> + +void +CloseApplication (GtkObject *object, + gpointer user_data); + +void +OnRun (GtkButton *button, + gpointer user_data); + +void +OnStep (GtkButton *button, + gpointer user_data); + +void +OnStepOver (GtkButton *button, + gpointer user_data); + +void +OnStop (GtkButton *button, + gpointer user_data); + +void +OnLoadHEX (GtkButton *button, + gpointer user_data); + +void +OnLoadLabels (GtkButton *button, + gpointer user_data); + +void +OnRunUntil (GtkButton *button, + gpointer user_data); + +void +OnQuit (GtkButton *button, + gpointer user_data); + +void +OnMemoryViewChoice (GtkComboBox *combobox, + gpointer user_data); @@ -0,0 +1,837 @@ +/* + + GEMMA - Z80 testbed + + Copyright (C) 2006 Ian Cowburn (ianc@noddybox.demon.co.uk) + + 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; either version 2 of the License, or + (at your option) any later version. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + +*/ +static const char id[]="$Id$"; + +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <string.h> +#include <ctype.h> + +#include "gemma.h" +#include "expr.h" +#include "gtkutil.h" +#include "support.h" + +#define HI(w) (((w)&0xff00)>>8) +#define LO(w) ((w)&0xff) +#define MK(h,l) (((Z80Word)(h))<<8|(l)) + +/* ---------------------------------------- GLOBALS +*/ +static Z80 *z80; +static Z80Byte mem[0x10000]; +static int memctl[256]; + +static sig_atomic_t stop=FALSE; + +static Z80Label *label=NULL; + +static GtkWidget *run_button; +static GtkWidget *step_button; +static GtkWidget *step_over_button; +static GtkWidget *stop_button; +static GtkWidget *run_until_button; + +static GtkWidget *top_window; +static GtkWidget *regview; +static GtkWidget *memview; +static GtkWidget *viewreg; +static GtkWidget *logview; +static GtkWidget *assemview; + +#define RUNNING(t) gtk_widget_set_sensitive(run_button,!t); \ + gtk_widget_set_sensitive(step_button,!t); \ + gtk_widget_set_sensitive(step_over_button,!t); \ + gtk_widget_set_sensitive(run_until_button,!t); \ + gtk_widget_set_sensitive(stop_button,t); + + +/* ---------------------------------------- PROTOS +*/ +static void Log(const char *format, ...); +static Z80Word Address(const char *p); +static void *Malloc(size_t len); +static void *Realloc(void *p, size_t len); + + +/* ---------------------------------------- DYNAMIC STRINGS +*/ + +typedef struct +{ + size_t len; + char *text; +} *DString; + + +#define BLOCKSIZE 512 + + +DString DSInit(void) +{ + DString ds; + + ds=Malloc(sizeof *ds); + + ds->len=0; + ds->text=Malloc(BLOCKSIZE); + ds->text[0]=0; + + return ds; +} + + +void DSFree(DString ds) +{ + if (ds) + { + free(ds->text); + free(ds); + } +} + + +DString DSAddChar(DString to, char c) +{ + if (((to->len+2)%BLOCKSIZE)==0) + { + to->text=Realloc(to->text,(((to->len+2)/BLOCKSIZE)+1)*BLOCKSIZE); + } + + to->text[to->len++]=c; + to->text[to->len]=0; + + return to; +} + + +DString DSAdd(DString to, const char *from) +{ + to->len+=strlen(from); + to->text=Realloc(to->text,(((to->len+1)/BLOCKSIZE)+1)*BLOCKSIZE); + + strcat(to->text,from); + + return to; +} + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static void Log(const char *format, ...) +{ + static char buff[4096]; + va_list va; + + va_start(va,format); + vsprintf(buff,format,va); + va_end(va); + + AppendText(logview,buff); +} + + +static int StrEq(const char *a, const char *b) +{ + while(*a && *b && tolower(*a)==tolower(*b)) + { + a++; + b++; + } + + if (*a || *b) + return FALSE; + else + return TRUE; +} + + +static int Expand(void *client, const char *p, long *res) +{ + Z80State s; + int ok=TRUE; + + Z80GetState(z80,&s); + + if (StrEq(p,"AF")) + *res=s.AF; + else if (StrEq(p,"BC")) + *res=s.BC; + else if (StrEq(p,"DE")) + *res=s.DE; + else if (StrEq(p,"HL")) + *res=s.HL; + else if (StrEq(p,"IX")) + *res=s.IX; + else if (StrEq(p,"IY")) + *res=s.IY; + else if (StrEq(p,"SP")) + *res=s.SP; + else if (StrEq(p,"PC")) + *res=s.PC; + else if (StrEq(p,"A")) + *res=HI(s.AF); + else if (StrEq(p,"F")) + *res=LO(s.AF); + else if (StrEq(p,"B")) + *res=HI(s.BC); + else if (StrEq(p,"C")) + *res=LO(s.BC); + else if (StrEq(p,"D")) + *res=HI(s.DE); + else if (StrEq(p,"E")) + *res=LO(s.DE); + else if (StrEq(p,"H")) + *res=HI(s.HL); + else if (StrEq(p,"L")) + *res=LO(s.HL); + else if (StrEq(p,"AF_")) + *res=s.AF_; + else if (StrEq(p,"BC_")) + *res=s.BC_; + else if (StrEq(p,"DE_")) + *res=s.DE_; + else if (StrEq(p,"HL_")) + *res=s.HL_; + else if (StrEq(p,"A_")) + *res=HI(s.AF_); + else if (StrEq(p,"F_")) + *res=LO(s.AF_); + else if (StrEq(p,"B_")) + *res=HI(s.BC_); + else if (StrEq(p,"C_")) + *res=LO(s.BC_); + else if (StrEq(p,"D_")) + *res=HI(s.DE_); + else if (StrEq(p,"E_")) + *res=LO(s.DE_); + else if (StrEq(p,"H_")) + *res=HI(s.HL_); + else if (StrEq(p,"L_")) + *res=LO(s.HL_); + else if (StrEq(p,"IM")) + *res=s.IM; + else if (StrEq(p,"R")) + *res=s.R; + else if (StrEq(p,"IFF1")) + *res=s.IFF1; + else if (StrEq(p,"IFF2")) + *res=s.IFF2; + else if (p[0]=='@') + { + Z80Word n; + + n=Address(p+1); + *res=mem[n]; + } + else if (p[0]=='#') + { + Z80Word n; + + n=Address(p+1); + *res=MK(mem[n+1],mem[n]); + } + else /* Check for labels */ + { + int f; + + ok=FALSE; + + for(f=0;label && label[f].label;f++) + { + if (StrEq(p,label[f].label)) + { + *res=label[f].address; + ok=TRUE; + break; + } + } + } + + return ok; +} + + +static Z80Word Address(const char *p) +{ + long e=0; + + if (!ExprEval(p,&e,Expand,z80)) + Log("%s\n",ExprError()); + + return (Z80Word)e; +} + + +static void *Malloc(size_t len) +{ + void *n; + + n=malloc(len); + + if (!n) + { + fprintf(stderr,"malloc failed\n"); + exit(EXIT_FAILURE); + } + + return n; +} + +static void *Realloc(void *p, size_t len) +{ + void *n; + + n=realloc(p,len); + + if (!n) + { + fprintf(stderr,"realloc failed\n"); + exit(EXIT_FAILURE); + } + + return n; +} + +static char *StrCopy(const char *p) +{ + return strcpy(Malloc(strlen(p)+1),p); +} + +static const int ToHex(char c) +{ + c=toupper(c); + + if (c>='0' && c<='9') + return c-'0'; + + if (c>='A' && c<='F') + return c-'A'+10; + + return 0; +} + +static void FlagString(DString s, Z80Byte flag, Z80Byte last) +{ + static char buff[32]; + static char *c[]={"S","Z","5","H","3","P","N","C"}; + int f; + + sprintf(buff,"%-10.10s: ","Flags"); + + DSAdd(s,buff); + + for(f=0;f<8;f++) + { + int b=1<<(7-f); + + if ((last&b)!=(flag&b)) + { + DSAdd(s,"<span foreground=\"white\" background=\"black\">"); + } + + if (flag&b) + { + DSAdd(s,c[f]); + } + else + { + DSAdd(s,"-"); + } + + if ((last&b)!=(flag&b)) + { + DSAdd(s,"</span>"); + } + } +} + + +static void DisplayState(DString s, const char *label, + int width, Z80Val val, Z80Val last) +{ + static char buff[128]; + + sprintf(buff,"%s: %s%*.*lX</span>", + label, + (last==val) ? + "<span>" : + "<span foreground=\"white\" background=\"black\">", + width,width, + val); + + DSAdd(s,buff); +} + + +/* ---------------------------------------- MEMORY +*/ +static Z80Byte ReadPort(Z80 *z80, Z80Word addr) +{ + Z80Byte b=0xff; + Z80Word ptr; + Z80State s; + char expr[1024]; + char *p; + + Z80GetState(z80,&s); + + switch(addr&0xff) + { + case 0x80: + ptr=MK(mem[1],mem[0]); + + p=expr; + + while(mem[ptr]) + *p++=mem[ptr++]; + + *p=0; + + b=(Z80Byte)Address(expr); + + /* Log("%s -> %u\n",expr,b); */ + + break; + + case 0x81: + ptr=s.DE; + + p=expr; + + while(mem[ptr]) + *p++=mem[ptr++]; + + *p=0; + + b=(Z80Byte)Address(expr); + + break; + + default: + Log("Read from port 0x%4.4x\n",(int)addr); + break; + } + + return b; +} + + +static void WritePort(Z80 *z80, Z80Word addr, Z80Byte val) +{ + Z80State s; + DString ds; + + ds=DSInit(); + Z80GetState(z80,&s); + + switch(addr&0xff) + { + case 0x80: + DSAddChar(ds,val); + break; + + case 0x81: + DSAdd(ds,"Stop requested via OUT(0x81)\n"); + stop=TRUE; + break; + + case 0x82: + while(mem[s.DE]!='$') + { + if (isspace(mem[s.DE]) || isprint(mem[s.DE])) + { + DSAddChar(ds,mem[s.DE]); + } + + s.DE++; + } + break; + + case 0x83: + while(mem[s.DE]) + { + DSAddChar(ds,mem[s.DE]); + s.DE++; + } + break; + + default: + Log("Wrote 0x%2.2x to port 0x%4.4x\n",(int)val,(int)addr); + return; + } + + Log(ds->text); + DSFree(ds); +} + + +static int Halt(Z80 *z80, Z80Val v) +{ + + Log("**** Processor halted\n"); + DialogOK("Processor halted\n"); + stop=TRUE; + return FALSE; +} + + +/* ---------------------------------------- EXPORTED FUNCTIONS +*/ +void GEMMA_UpdateDisplay(GEMMA_View view) +{ + if (view&UPDATE_ASSEM_VIEW) + { + Z80State reg; + DString ds; + int f; + + ds=DSInit(); + Z80GetState(z80,®); + DSAdd(ds,"<tt>"); + + for(f=0;f<20;f++) + { + if (f==0) + { + DSAdd(ds,"<span foreground=\"white\" background=\"black\">"); + } + + DSAdd(ds,Z80Disassemble(z80,®.PC)); + + if (f==0) + { + DSAdd(ds,"</span>"); + } + + DSAddChar(ds,'\n'); + } + + DSAdd(ds,"</tt>"); + gtk_label_set_markup(GTK_LABEL(assemview),ds->text); + + DSFree(ds); + } + + if (view&UPDATE_REG_VIEW) + { + static int reg_once=FALSE; + static Z80State last_reg; + Z80State reg; + DString ds; + + ds=DSInit(); + Z80GetState(z80,®); + + if (!reg_once) + { + last_reg=reg; + } + + DSAdd(ds,"<tt>"); + + DisplayState(ds,"A",2,HI(reg.AF),HI(last_reg.AF)); + DSAdd(ds," "); + FlagString(ds,LO(reg.AF),LO(last_reg.AF)); + DSAdd(ds,"\n"); + + DisplayState(ds,"BC",4,reg.BC,last_reg.BC); + DSAdd(ds," "); + DisplayState(ds,"DE",4,reg.DE,last_reg.DE); + DSAdd(ds," "); + DisplayState(ds,"HL",4,reg.HL,last_reg.HL); + DSAdd(ds,"\n"); + + DisplayState(ds,"SP",4,reg.SP,last_reg.SP); + DSAdd(ds," "); + DisplayState(ds,"IX",4,reg.IX,last_reg.IX); + DSAdd(ds," "); + DisplayState(ds,"IY",4,reg.IY,last_reg.IY); + DSAdd(ds,"\n"); + + DisplayState(ds,"AF'",4,reg.AF_,last_reg.AF_); + DSAdd(ds," "); + DisplayState(ds,"BC'",4,reg.BC_,last_reg.BC_); + DSAdd(ds," "); + DisplayState(ds,"DE'",4,reg.DE_,last_reg.DE_); + DSAdd(ds," "); + DisplayState(ds,"HL'",4,reg.HL_,last_reg.HL_); + DSAdd(ds,"\n"); + + DisplayState(ds,"PC",4,reg.PC,last_reg.PC); + DSAdd(ds,"\n"); + DisplayState(ds,"R",4,reg.R,last_reg.R); + DSAdd(ds,"\n"); + DisplayState(ds,"CYCLES",8,reg.cycle,last_reg.cycle); + DSAdd(ds,"\n"); + + DSAdd(ds,"</tt>"); + + gtk_label_set_markup(GTK_LABEL(regview),ds->text); + + DSFree(ds); + + last_reg=reg; + } +} + + +void GEMMA_LoadHEX(const char *path) +{ + FILE *fp; + char buff[1024]; + int done=FALSE; + + if (!(fp=fopen(path,"r"))) + { + Log("Failed to open %s\n",path); + return; + } + + while(!done) + { + if (!fgets(buff,sizeof buff,fp)) + { + Log("Missing EOF record\n"); + done=TRUE; + } + + if (!done && buff[0]!=':') + { + Log("Invalid Intel HEX file\n"); + done=TRUE; + } + + if (!done && buff[8]=='1') + { + Log("<EOF>\n"); + done=TRUE; + } + + if (!done) + { + Z80Word addr; + int len; + int f; + + len=ToHex(buff[1])<<4|ToHex(buff[2]); + + addr=ToHex(buff[3])<<12|ToHex(buff[4])<<8| + ToHex(buff[5])<<4|ToHex(buff[6]); + + Log("Segment of 0x%2.2x bytes at address 0x%4.4x\n",len,addr); + + for(f=0;f<len;f++) + { + Z80Byte b; + + b=ToHex(buff[f*2+9])<<4|ToHex(buff[f*2+10]); + mem[addr++]=b; + } + } + } + + fclose(fp); + + GEMMA_UpdateDisplay(UPDATE_ALL_VIEWS); +} + + +void GEMMA_LoadLabels(const char *path) +{ + FILE *fp; + int f; + char buff[512]; + + if (!(fp=fopen(path,"r"))) + { + Log("Failed to open %s\n",path); + return; + } + + for(f=0;label && label[f].label;f++) + free((void *)label[f].label); + + free(label); + label=NULL; + f=0; + + while(fgets(buff,sizeof buff,fp)) + { + char *name=NULL; + char *addr=NULL; + + if (strlen(buff) && buff[strlen(buff)-1]=='\n') + buff[strlen(buff)-1]=0; + + name=strtok(buff," \t"); + + if (name) + addr=strtok(NULL," \t"); + + if (name && addr) + { + label=Realloc(label,sizeof(*label)*(f+2)); + + label[f].label=StrCopy(name); + label[f].address=Address(addr); + + f++; + } + } + + if (label) + label[f].label=NULL; + + Z80SetLabels(label); + + fclose(fp); +} + + +void GEMMA_Step(void) +{ + Z80SingleStep(z80); + GEMMA_UpdateDisplay(UPDATE_ALL_VIEWS); +} + + +void GEMMA_StepOver(void) +{ + Z80Word next; + Z80State reg; + + stop=FALSE; + + Z80GetState(z80,®); + next=reg.PC; + Z80Disassemble(z80,&next); + + RUNNING(TRUE); + + while(reg.PC!=next && !stop) + { + GEMMA_Step(); + Z80GetState(z80,®); + gtk_main_iteration_do(FALSE); + } + + RUNNING(FALSE); +} + + +void GEMMA_Run(void) +{ + stop=FALSE; + + RUNNING(TRUE); + + while(!stop) + { + GEMMA_Step(); + gtk_main_iteration_do(FALSE); + } + + RUNNING(FALSE); +} + + +void GEMMA_RunUntil(const char *expr) +{ + stop=FALSE; + + RUNNING(TRUE); + + while(!stop) + { + long e; + + if (!ExprEval(expr,&e,Expand,z80)) + { + Log("%s\n",ExprError()); + stop=TRUE; + continue; + } + + if (e) + { + Log("%s TRUE\n",expr); + stop=TRUE; + continue; + } + + GEMMA_Step(); + gtk_main_iteration_do(FALSE); + } + + RUNNING(FALSE); +} + + +void GEMMA_Stop(void) +{ + stop=TRUE; +} + + +void GEMMA_Init(GtkWidget *top) +{ + int f; + + for(f=0;f<256;f++) memctl[f]=1; + + z80=Z80Init(mem,memctl,WritePort,ReadPort); + + if (!z80) + { + fprintf(stderr,"Failed to initialise Z80\n"); + exit(EXIT_FAILURE); + } + + Z80LodgeCallback(z80,eZ80_Halt,Halt); + + top_window=top; + regview=lookup_widget(top_window,"register_view"); + memview=lookup_widget(top_window,"memory_view"); + viewreg=lookup_widget(top_window,"memory_view_choice"); + logview=lookup_widget(top_window,"log_view"); + assemview=lookup_widget(top_window,"assem_view"); +} + + +void GEMMA_Interrupt(int nmi) +{ + if (nmi) + { + Z80NMI(z80); + } + else + { + Z80Interrupt(z80,0); + } +} + + +/* END OF FILE */ diff --git a/gemma.glade b/gemma.glade index 3e944ac..a38cc57 100644 --- a/gemma.glade +++ b/gemma.glade @@ -4,145 +4,149 @@ <glade-interface> <widget class="GtkWindow" id="top_window"> + <property name="width_request">900</property> + <property name="height_request">600</property> <property name="visible">True</property> <property name="title" translatable="yes">GEMMA</property> <property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="window_position">GTK_WIN_POS_NONE</property> <property name="modal">False</property> - <property name="default_width">770</property> - <property name="default_height">640</property> - <property name="resizable">True</property> + <property name="default_width">800</property> + <property name="default_height">600</property> + <property name="resizable">False</property> <property name="destroy_with_parent">True</property> <property name="decorated">True</property> <property name="skip_taskbar_hint">False</property> <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> <property name="urgency_hint">False</property> <child> - <widget class="GtkVBox" id="vbox2"> + <widget class="GtkVBox" id="vbox4"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> - <widget class="GtkVBox" id="vbox3"> - <property name="border_width">3</property> + <widget class="GtkHBox" id="hbox2"> <property name="visible">True</property> - <property name="homogeneous">False</property> + <property name="homogeneous">True</property> <property name="spacing">0</property> <child> - <widget class="GtkVPaned" id="vpaned1"> + <widget class="GtkLabel" id="assem_view"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="position">0</property> + <property name="label" translatable="yes"><b>Assembler View</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="register_view"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Regsiter View</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="height_request">1</property> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> <child> - <widget class="GtkHPaned" id="hpaned1"> + <widget class="GtkComboBox" id="memory_view_choice"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="position">0</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="assem_view"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">False</property> - <property name="fixed_height_mode">True</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - </widget> - </child> - </widget> - <packing> - <property name="shrink">True</property> - <property name="resize">False</property> - </packing> - </child> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow3"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="register_view"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">False</property> - <property name="fixed_height_mode">True</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - </widget> - </child> - </widget> - <packing> - <property name="shrink">True</property> - <property name="resize">True</property> - </packing> - </child> + <property name="items" translatable="yes">SP +HL +IX +IY +BC +DE</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + <signal name="changed" handler="OnMemoryViewChoice" last_modification_time="Tue, 29 Aug 2006 23:31:24 GMT"/> </widget> <packing> - <property name="shrink">True</property> - <property name="resize">False</property> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> </packing> </child> <child> - <widget class="GtkScrolledWindow" id="scrolledwindow1"> + <widget class="GtkLabel" id="memory_view"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTextView" id="log_view"> - <property name="border_width">1</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">False</property> - <property name="overwrite">False</property> - <property name="accepts_tab">True</property> - <property name="justification">GTK_JUSTIFY_LEFT</property> - <property name="wrap_mode">GTK_WRAP_CHAR</property> - <property name="cursor_visible">False</property> - <property name="pixels_above_lines">0</property> - <property name="pixels_below_lines">0</property> - <property name="pixels_inside_wrap">0</property> - <property name="left_margin">0</property> - <property name="right_margin">0</property> - <property name="indent">0</property> - <property name="text" translatable="yes"></property> - </widget> - </child> + <property name="label" translatable="yes"><b>Memory View</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> </widget> <packing> - <property name="shrink">True</property> - <property name="resize">True</property> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> </packing> </child> </widget> @@ -154,93 +158,163 @@ </child> <child> - <widget class="GtkHButtonBox" id="hbuttonbox1"> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_START</property> - <property name="spacing">10</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> <child> - <widget class="GtkButton" id="run_button"> + <widget class="GtkTextView" id="log_view"> <property name="visible">True</property> - <property name="can_default">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Run</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> + <property name="editable">False</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_CHAR</property> + <property name="cursor_visible">False</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">0</property> + <property name="right_margin">0</property> + <property name="indent">0</property> + <property name="text" translatable="yes"></property> </widget> </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> - <child> - <widget class="GtkButton" id="step_button"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Step</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="border_width">4</property> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_SPREAD</property> + <property name="spacing">0</property> - <child> - <widget class="GtkButton" id="step_over_button"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Step Over</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> + <child> + <widget class="GtkButton" id="run_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Run</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnRun" last_modification_time="Mon, 28 Aug 2006 20:30:42 GMT"/> + </widget> + </child> - <child> - <widget class="GtkButton" id="stop_button"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Stop</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> + <child> + <widget class="GtkButton" id="step_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Step</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnStep" last_modification_time="Mon, 28 Aug 2006 20:30:34 GMT"/> + </widget> + </child> - <child> - <widget class="GtkButton" id="load_button"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Load HEX</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> + <child> + <widget class="GtkButton" id="step_over_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Step Over</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnStepOver" last_modification_time="Mon, 28 Aug 2006 20:30:21 GMT"/> + </widget> + </child> - <child> - <widget class="GtkButton" id="quit_button"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Quit</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> + <child> + <widget class="GtkButton" id="stop_button"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Stop</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnStop" last_modification_time="Mon, 28 Aug 2006 20:30:16 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="load_hex_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Load HEX</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="activate" handler="OnLoadHEX" last_modification_time="Mon, 28 Aug 2006 20:23:36 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="load_labels_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Load Labels</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnLoadLabels" last_modification_time="Mon, 28 Aug 2006 20:30:05 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="run_until_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Run Until</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnRunUntil" last_modification_time="Mon, 28 Aug 2006 20:30:00 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="quit_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Quit</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnQuit" last_modification_time="Mon, 28 Aug 2006 20:29:15 GMT"/> </widget> - <packing> - <property name="padding">7</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> </child> </widget> <packing> <property name="padding">0</property> - <property name="expand">True</property> + <property name="expand">False</property> <property name="fill">True</property> </packing> </child> @@ -0,0 +1,56 @@ +/* + + GEMMA - Z80 testbed + + Copyright (C) 2006 Ian Cowburn (ianc@noddybox.demon.co.uk) + + 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; either version 2 of the License, or + (at your option) any later version. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + +*/ + +#ifndef GEMMA_H +#define GEMMA_H "$Id$" + +#include <gtk/gtk.h> +#include "z80.h" + +typedef enum +{ + UPDATE_ASSEM_VIEW=0x01, + UPDATE_REG_VIEW=0x02, + UPDATE_MEM_VIEW=0x04, + UPDATE_ALL_VIEWS=UPDATE_ASSEM_VIEW|UPDATE_REG_VIEW|UPDATE_MEM_VIEW +} GEMMA_View; + +void GEMMA_Init(GtkWidget *top); +void GEMMA_LoadHEX(const char *path); +void GEMMA_LoadLabels(const char *path); +void GEMMA_UpdateDisplay(GEMMA_View view); +void GEMMA_Step(void); +void GEMMA_StepOver(void); +void GEMMA_Run(void); +void GEMMA_RunUntil(const char *expr); +void GEMMA_Stop(void); +void GEMMA_Interrupt(int nmi); + +#endif + +/* END OF FILE */ + + @@ -49,7 +49,7 @@ static int selected=FALSE; static char saved_path[PATH_MAX+1]; -/* ---------------------------------------- CALLBACKS +/* ---------------------------------------- PRIVATE FUNCTIONS */ static void Callback(GtkWidget *w, gpointer data) { @@ -85,7 +85,7 @@ static void FselCallback(GtkWidget *w, gpointer data) } -/* ---------------------------------------- DialogParent() +/* ---------------------------------------- EXPORTED FUNCTIONS */ void DialogParent(GtkWidget *w) { @@ -93,8 +93,6 @@ void DialogParent(GtkWidget *w) } -/* ---------------------------------------- DialogOK() -*/ void DialogOK(const char *format, ...) { va_list va; @@ -133,8 +131,6 @@ void DialogOK(const char *format, ...) } -/* ---------------------------------------- DialogYesNo() -*/ int DialogYesNo(const char *format, ...) { va_list va; @@ -194,8 +190,6 @@ int DialogYesNo(const char *format, ...) } -/* ---------------------------------------- DialogFSelect() -*/ int DialogFSelect(const char *title, char path[]) { dialog=gtk_file_selection_new(title); @@ -236,4 +230,15 @@ int DialogFSelect(const char *title, char path[]) } +void AppendText(GtkWidget *w, const char *text) +{ + GtkTextBuffer *buff; + GtkTextIter end; + + buff=gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)); + gtk_text_buffer_get_end_iter(buff,&end); + gtk_text_buffer_insert(buff,&end,text,-1); +} + + /* END OF FILE */ @@ -55,6 +55,10 @@ int DialogYesNo(const char *format, ...); */ int DialogFSelect(const char *title, char path[]); +/* Append text to a text view +*/ +void AppendText(GtkWidget *w, const char *text); + #endif @@ -33,17 +33,31 @@ static const char ident[]="$Id$"; #include "interface.h" #include "support.h" +#include "gtkutil.h" +#include "gemma.h" + int main (int argc, char *argv[]) { - GtkWidget *top_window; + GtkWidget *top_window; + + gtk_set_locale (); + gtk_init (&argc, &argv); + + top_window = create_top_window (); + gtk_widget_show (top_window); - gtk_set_locale (); - gtk_init (&argc, &argv); + DialogParent(top_window); + GEMMA_Init(top_window); + GEMMA_UpdateDisplay(UPDATE_ALL_VIEWS); - top_window = create_top_window (); - gtk_widget_show (top_window); + AppendText(lookup_widget(top_window,"log_view"), + "GEMMA, Copyright (C) 2006 Ian Cowburn\n" + "GEMMA comes with ABSOLUTELY NO WARRANTY\n" + "This is free software, and you are welcome\n" + "to redistribute it under certain conditions;\n" + "See the GNU General Public License for details.\n"); - gtk_main (); - return 0; + gtk_main (); + return 0; } @@ -179,6 +179,12 @@ void Z80Reset(Z80 *cpu) } +void Z80SetPC(Z80 *cpu,Z80Word PC) +{ + cpu->PC=PC; +} + + void Z80ResetCycles(Z80 *cpu, Z80Val cycles) { cpu->cycle=cycles; @@ -174,6 +174,11 @@ Z80 *Z80Init(Z80Memory memory, void Z80Reset(Z80 *cpu); +/* Sets the PC +*/ +void Z80SetPC(Z80 *cpu, Z80Word PC); + + /* Sets the cycle count to the specified count */ void Z80ResetCycles(Z80 *cpu, Z80Val cycles); |