summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile10
-rw-r--r--callbacks.c74
-rw-r--r--callbacks.h40
-rw-r--r--gemma.c837
-rw-r--r--gemma.glade420
-rw-r--r--gemma.h56
-rw-r--r--gtkutil.c21
-rw-r--r--gtkutil.h4
-rw-r--r--main.c28
-rw-r--r--z80.c6
-rw-r--r--z80.h5
11 files changed, 1309 insertions, 192 deletions
diff --git a/Makefile b/Makefile
index d309ea7..09d32ab 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
diff --git a/gemma.c b/gemma.c
new file mode 100644
index 0000000..015362b
--- /dev/null
+++ b/gemma.c
@@ -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,&reg);
+ DSAdd(ds,"<tt>");
+
+ for(f=0;f<20;f++)
+ {
+ if (f==0)
+ {
+ DSAdd(ds,"<span foreground=\"white\" background=\"black\">");
+ }
+
+ DSAdd(ds,Z80Disassemble(z80,&reg.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,&reg);
+
+ 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,&reg);
+ next=reg.PC;
+ Z80Disassemble(z80,&next);
+
+ RUNNING(TRUE);
+
+ while(reg.PC!=next && !stop)
+ {
+ GEMMA_Step();
+ Z80GetState(z80,&reg);
+ 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">&lt;b&gt;Assembler View&lt;/b&gt;</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">&lt;b&gt;Regsiter View&lt;/b&gt;</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">&lt;b&gt;Memory View&lt;/b&gt;</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>
diff --git a/gemma.h b/gemma.h
new file mode 100644
index 0000000..c7ccc1d
--- /dev/null
+++ b/gemma.h
@@ -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 */
+
+
diff --git a/gtkutil.c b/gtkutil.c
index da08e1b..b5ec30c 100644
--- a/gtkutil.c
+++ b/gtkutil.c
@@ -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 */
diff --git a/gtkutil.h b/gtkutil.h
index 0385a5e..46717d2 100644
--- a/gtkutil.h
+++ b/gtkutil.h
@@ -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
diff --git a/main.c b/main.c
index f4f66a4..f39e133 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
diff --git a/z80.c b/z80.c
index cd2371a..a974c40 100644
--- a/z80.c
+++ b/z80.c
@@ -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;
diff --git a/z80.h b/z80.h
index 3b3220e..5ac28b7 100644
--- a/z80.h
+++ b/z80.h
@@ -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);