Initial emulator implementation

master
Marco Maccaferri 2019-01-26 08:53:09 +01:00
rodzic 034c82c2a8
commit 28217319ac
6 zmienionych plików z 988 dodań i 15 usunięć

Wyświetl plik

@ -130,6 +130,7 @@ public class Application {
SerialTerminal terminal;
DebugTerminal debugTerminal;
Emulator emulator;
Z80 proc;
MemIoOps memIoOps;
@ -958,6 +959,21 @@ public class Application {
new MenuItem(menu, SWT.SEPARATOR);
item = new MenuItem(menu, SWT.PUSH);
item.setText("Emulator\tCtrl+Shift+E");
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'E');
item.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event e) {
try {
handleOpenEmulator();
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Serial Terminal\tCtrl+Shift+T");
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'T');
@ -2376,7 +2392,7 @@ public class Application {
return;
}
memIoOps = new MemIoOps() {
memIoOps = new MemIoOps(65536, 256) {
public final static int SIOA_D = 0x81;
public final static int SIOA_C = 0x80;
@ -2876,6 +2892,21 @@ public class Application {
}
private void handleOpenEmulator() {
if (emulator == null) {
emulator = new Emulator();
emulator.open();
emulator.getShell().addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
emulator = null;
}
});
}
emulator.setFocus();
}
static {
Display.setAppName(APP_TITLE);
Display.setAppVersion(APP_VERSION);

Wyświetl plik

@ -0,0 +1,488 @@
/*
* Copyright (c) 2018-19 Marco Maccaferri and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.maccasoft.tools;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.jface.databinding.swt.DisplayRealm;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import com.maccasoft.tools.internal.ImageRegistry;
import nl.grauw.glass.AssemblyException;
import nl.grauw.glass.Source;
import nl.grauw.glass.SourceBuilder;
public class Emulator {
Display display;
Shell shell;
Composite container;
Terminal term;
Combo cursorKeys;
PipedOutputStream os;
PipedInputStream is;
Machine machine;
Preferences preferences;
public Emulator() {
}
public void open() {
display = Display.getDefault();
preferences = Preferences.getInstance();
shell = new Shell(display);
shell.setText(Application.APP_TITLE);
shell.setData(this);
Image[] images = new Image[] {
ImageRegistry.getImageFromResources("app128.png"),
ImageRegistry.getImageFromResources("app64.png"),
ImageRegistry.getImageFromResources("app48.png"),
ImageRegistry.getImageFromResources("app32.png"),
ImageRegistry.getImageFromResources("app16.png"),
};
shell.setImages(images);
Menu menu = new Menu(shell, SWT.BAR);
createFileMenu(menu);
createEditMenu(menu);
createHelpMenu(menu);
shell.setMenuBar(menu);
GridLayout layout = new GridLayout(1, false);
layout.marginWidth = layout.marginHeight = 0;
shell.setLayout(layout);
Control control = createContents(shell);
control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Rectangle screen = display.getClientArea();
Point size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
Rectangle rect = shell.computeTrim(0, 0, size.x, size.y);
rect.x = (screen.width - rect.width) / 2;
rect.y = (screen.height - rect.height) / 2;
if (rect.y < 0) {
rect.height += rect.y * 2;
rect.y = 0;
}
shell.setLocation(rect.x, rect.y);
shell.setSize(rect.width, rect.height);
shell.open();
machine = new Machine() {
@Override
protected void run() {
try {
String s = preferences.getRomImage1();
if (s != null && !"".equals(s)) {
if (s.toUpperCase().endsWith(".ASM")) {
byte[] rom = compile(new File(s));
if (rom == null) {
return;
}
machine.setRom(preferences.getRomAddress1(), rom);
}
else {
machine.setRom(preferences.getRomAddress1(), new File(s));
}
}
s = preferences.getRomImage2();
if (s != null && !"".equals(s)) {
if (s.toUpperCase().endsWith(".ASM")) {
byte[] rom = compile(new File(s));
if (rom == null) {
return;
}
machine.setRom(preferences.getRomAddress2(), rom);
}
else {
machine.setRom(preferences.getRomAddress2(), new File(s));
}
}
} catch (Exception e) {
e.printStackTrace();
return;
}
super.run();
}
@Override
public int inPort(int port) {
switch (port & 0xFF) {
case SIOA_C:
try {
if (is.available() > 0) {
return 0x04 + 0x01;
}
} catch (Exception e) {
e.printStackTrace();
}
return 0x04; // Always return TX buffer empty
case SIOA_D:
try {
if (is.available() > 0) {
return is.read();
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
return super.inPort(port);
}
@Override
public void outPort(int port, int value) {
switch (port & 0xFF) {
case SIOA_D:
display.syncExec(new Runnable() {
@Override
public void run() {
term.write(value);
}
});
break;
case SIOB_D:
break;
}
super.outPort(port, value);
}
};
String s = preferences.getCompactFlashImage();
if (s != null && !"".equals(s)) {
machine.setCompactFlash(new File(s));
}
machine.reset();
machine.start();
}
void createFileMenu(Menu parent) {
final Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
MenuItem item = new MenuItem(parent, SWT.CASCADE);
item.setText("&File");
item.setMenu(menu);
item = new MenuItem(menu, SWT.PUSH);
item.setText("Close");
item.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event e) {
shell.dispose();
}
});
}
void createEditMenu(Menu parent) {
Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
MenuItem item = new MenuItem(parent, SWT.CASCADE);
item.setText("&Edit");
item.setMenu(menu);
item = new MenuItem(menu, SWT.PUSH);
item.setText("Paste\tShift+Ins");
item.setAccelerator(SWT.MOD2 + SWT.INSERT);
item.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event e) {
try {
term.pasteFromClipboard();
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
}
void createHelpMenu(Menu parent) {
Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
MenuItem item = new MenuItem(parent, SWT.CASCADE);
item.setText("&Help");
item.setMenu(menu);
item = new MenuItem(menu, SWT.PUSH);
item.setText("About " + Application.APP_TITLE);
item.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event e) {
AboutDialog dlg = new AboutDialog(shell);
dlg.open();
}
});
}
protected Control createContents(Composite parent) {
container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
layout.marginWidth = layout.marginHeight = 0;
container.setLayout(layout);
container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
term = new Terminal(container) {
@Override
protected void writeByte(byte b) {
try {
while (is.available() >= 16) {
Thread.yield();
}
os.write(b);
} catch (IOException e) {
e.printStackTrace();
}
}
};
Rectangle rect = term.getBounds();
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.widthHint = rect.width;
gridData.heightHint = rect.height;
term.setLayoutData(gridData);
createBottomControls(container);
try {
is = new PipedInputStream();
os = new PipedOutputStream(is);
} catch (IOException e1) {
e1.printStackTrace();
}
container.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (machine != null) {
machine.stop();
}
try {
if (os != null) {
os.close();
}
} catch (Exception e1) {
// Do nothing
}
}
});
return container;
}
void createBottomControls(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
layout.marginBottom = layout.marginHeight;
layout.marginLeft = layout.marginRight = layout.marginWidth;
layout.marginWidth = layout.marginHeight = 0;
container.setLayout(layout);
container.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
Label label = new Label(container, SWT.NONE);
label.setText("Keys");
cursorKeys = new Combo(container, SWT.DROP_DOWN | SWT.READ_ONLY);
cursorKeys.setItems(new String[] {
"VT-100",
"WordStar"
});
cursorKeys.select(0);
cursorKeys.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
switch (cursorKeys.getSelectionIndex()) {
case 0:
term.setCursorKeys(Terminal.CURSORS_VT100);
break;
case 1:
term.setCursorKeys(Terminal.CURSORS_WORDSTAR);
break;
}
term.setFocus();
}
});
label = new Label(container, SWT.NONE);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
Button button = new Button(container, SWT.PUSH);
button.setText("Reset");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
try {
while (is.available() > 0) {
is.read();
}
} catch (IOException e1) {
e1.printStackTrace();
}
machine.reset();
term.setFocus();
}
});
layout.numColumns = container.getChildren().length;
}
public void setFocus() {
term.setFocus();
}
byte[] compile(File file) {
System.out.print("Compiling " + file.getName() + "...");
try {
final List<File> includePaths = new ArrayList<File>();
if (file != null) {
includePaths.add(file.getParentFile());
}
String[] includes = preferences.getIncludes();
if (includes != null) {
for (int i = 0; i < includes.length; i++) {
includePaths.add(new File(includes[i]));
}
}
SourceBuilder builder = new SourceBuilder(includePaths) {
@Override
public Source parse(File sourceFile) {
System.out.print("\r\nCompiling " + sourceFile.getName() + "...");
return super.parse(sourceFile);
}
};
Source source = builder.parse(new InputStreamReader(new FileInputStream(file)), file);
source.register();
source.expand();
source.resolve();
System.out.println();
return new BinaryBuilder(source).build();
} catch (AssemblyException ex) {
StringBuilder sb = new StringBuilder();
Iterator<AssemblyException.Context> iter = ex.contexts.iterator();
if (iter.hasNext()) {
AssemblyException.Context context = iter.next();
sb.append(context.file.getName());
sb.append(":");
sb.append(context.line + 1);
if (context.column != -1) {
sb.append(":");
sb.append(context.column);
}
sb.append(": error: ");
sb.append(ex.getPlainMessage());
}
System.out.println();
System.err.println(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Shell getShell() {
return shell;
}
static {
System.setProperty("SWT_GTK3", "0");
}
public static void main(String[] args) {
final Display display = new Display();
Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
@Override
public void run() {
try {
Emulator emulator = new Emulator();
emulator.open();
while (display.getShells().length != 0) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
} catch (Exception e) {
e.printStackTrace();
return;
}
}
});
display.dispose();
}
}

Wyświetl plik

@ -0,0 +1,258 @@
/*
* Copyright (c) 2018-19 Marco Maccaferri and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.maccasoft.tools;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import z80core.MemIoOps;
import z80core.Z80;
public class Machine extends MemIoOps {
public final static int SIOA_C = 0x80;
public final static int SIOA_D = 0x81;
public final static int SIOB_C = 0x82;
public final static int SIOB_D = 0x83;
public final static int CF_DATA = 0x10;
public final static int CF_FEATURES = 0x11;
public final static int CF_ERROR = 0x11;
public final static int CF_SECCOUNT = 0x12;
public final static int CF_SECTOR = 0x13;
public final static int CF_CYL_LOW = 0x14;
public final static int CF_CYL_HI = 0x15;
public final static int CF_HEAD = 0x16;
public final static int CF_STATUS = 0x17;
public final static int CF_COMMAND = 0x17;
public final static int CF_LBA0 = 0x13;
public final static int CF_LBA1 = 0x14;
public final static int CF_LBA2 = 0x15;
public final static int CF_LBA3 = 0x16;
public final static int CF_READ_SEC = 0x20;
public final static int CF_WRITE_SEC = 0x30;
boolean page;
byte[] rom;
byte[] ram;
byte cfCommand;
byte[] cfLBA = new byte[4];
File cfFile;
RandomAccessFile cf;
Z80 proc;
Thread thread;
double clockNs;
long tstates;
public Machine() {
rom = new byte[16384];
ram = new byte[65536];
clockNs = 1000.0 / 7.3728;
proc = new Z80(this, null);
thread = new Thread(new Runnable() {
@Override
public void run() {
Machine.this.run();
}
});
}
public void setRom(int address, File file) throws IOException {
InputStream is = new FileInputStream(file);
is.read(rom, address, rom.length - address);
is.close();
}
public void setRom(int address, byte[] rom) throws IOException {
System.arraycopy(rom, 0, this.rom, address, Math.min(this.rom.length - address, rom.length));
}
public void setClock(double freq) {
clockNs = 1000.0 / freq;
}
public void setCompactFlash(File file) {
this.cfFile = file;
}
public void start() {
try {
if (cfFile != null) {
cf = new RandomAccessFile(cfFile, "rw");
}
} catch (IOException e) {
e.printStackTrace();
}
thread.start();
}
protected void run() {
long ns = System.nanoTime();
while (!Thread.interrupted()) {
synchronized (proc) {
long current = System.nanoTime();
long tstates = getTstates() + (long) ((current - ns) / clockNs);
while (getTstates() < tstates) {
proc.execute();
}
ns = current;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
break;
}
}
}
@Override
public void reset() {
synchronized (proc) {
page = false;
tstates = 0;
proc.reset();
super.reset();
}
}
@Override
public int fetchOpcode(int address) {
tstates += 4; // 3 clocks to fetch opcode from RAM and 1 execution clock
if (!page && address < rom.length) {
return rom[address & 0xFFFF] & 0xff;
}
return ram[address & 0xFFFF] & 0xff;
}
@Override
public int inPort(int port) {
tstates += 4; // 4 clocks for read byte from bus
switch (port & 0xFF) {
case CF_DATA:
if (cfCommand == CF_READ_SEC) {
try {
if (cf != null) {
return (byte) cf.read();
}
} catch (IOException e) {
e.printStackTrace();
}
}
break;
case CF_STATUS:
return 0x40; // CF ready
case SIOA_C:
return 0x04; // Always return TX buffer empty
case SIOB_C:
return 0x04; // Always return TX buffer empty
}
return 0;
}
@Override
public void outPort(int port, int value) {
tstates += 4; // 4 clocks for write byte to bus
switch (port & 0xFF) {
case CF_DATA:
if (cfCommand == CF_WRITE_SEC) {
try {
if (cf != null) {
cf.write(value & 0xFF);
}
} catch (IOException e) {
e.printStackTrace();
}
}
break;
case CF_COMMAND:
cfCommand = (byte) value;
if (cfCommand == CF_WRITE_SEC || cfCommand == CF_READ_SEC) {
try {
long addr = ((cfLBA[3] & 0x0F) << 24) | ((cfLBA[2] & 0xFF) << 16) | ((cfLBA[1] & 0xFF) << 8) | (cfLBA[0] & 0xFF);
if (cf != null) {
cf.seek(addr << 9);
}
} catch (IOException e) {
e.printStackTrace();
}
}
break;
case CF_LBA0:
cfLBA[0] = (byte) value;
break;
case CF_LBA1:
cfLBA[1] = (byte) value;
break;
case CF_LBA2:
cfLBA[2] = (byte) value;
break;
case CF_LBA3: {
cfLBA[3] = (byte) value;
break;
}
case 0x38: // ROM page
page = !page;
break;
}
}
@Override
public int peek8(int address) {
tstates += 3; // 3 clocks for read byte from RAM
if (!page && address < rom.length) {
return rom[address & 0xFFFF] & 0xff;
}
return ram[address & 0xFFFF] & 0xff;
}
@Override
public void poke8(int address, int value) {
tstates += 3; // 3 clocks for write byte to RAM
if (page || address >= rom.length) {
ram[address & 0xFFFF] = (byte) value;
}
}
@Override
public long getTstates() {
return tstates;
}
public void stop() {
try {
thread.interrupt();
} catch (Exception e) {
// Do nothing
}
try {
if (cf != null) {
cf.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Wyświetl plik

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Marco Maccaferri and others.
* Copyright (c) 2018-19 Marco Maccaferri and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under
@ -89,6 +89,12 @@ public class Preferences {
String downloadCommand;
String xmodemCommand;
String romImage1;
int romAddress1;
String romImage2;
int romAddress2;
String compactFlashImage;
int lastUploadType;
String lastPath;
List<String> lru;
@ -368,6 +374,46 @@ public class Preferences {
this.lastUploadType = lastUploadType;
}
public String getRomImage1() {
return romImage1;
}
public void setRomImage1(String romImage) {
this.romImage1 = romImage;
}
public int getRomAddress1() {
return romAddress1;
}
public void setRomAddress1(int romAddress) {
this.romAddress1 = romAddress;
}
public String getRomImage2() {
return romImage2;
}
public void setRomImage2(String romImage) {
this.romImage2 = romImage;
}
public int getRomAddress2() {
return romAddress2;
}
public void setRomAddress2(int romAddress) {
this.romAddress2 = romAddress;
}
public String getCompactFlashImage() {
return compactFlashImage;
}
public void setCompactFlashImage(String compactFlashImage) {
this.compactFlashImage = compactFlashImage;
}
public void save() throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);

Wyświetl plik

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Marco Maccaferri and others.
* Copyright (c) 2018-19 Marco Maccaferri and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -27,6 +27,7 @@ import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
@ -73,6 +74,12 @@ public class PreferencesDialog extends Dialog {
Text downloadCommand;
Text xmodemCommand;
Text romImage1;
Text romAddress1;
Text romImage2;
Text romAddress2;
Text compactFlashImage;
Preferences preferences;
String defaultFont;
@ -96,7 +103,7 @@ public class PreferencesDialog extends Dialog {
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
if ("win32".equals(SWT.getPlatform())) {
defaultFont = StringConverter.asString(new FontData("Courier New", 9, SWT.NONE));
@ -119,6 +126,7 @@ public class PreferencesDialog extends Dialog {
createGeneralPage(stack);
createAssemblerPage(stack);
createEditorPage(stack);
createEmulatorPage(stack);
createFormatterPage(stack);
stackLayout.topControl = stack.getChildren()[0];
@ -146,7 +154,7 @@ public class PreferencesDialog extends Dialog {
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
pages.add("General");
@ -290,7 +298,7 @@ public class PreferencesDialog extends Dialog {
label = new Label(composite, SWT.NONE);
label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));
((GridData) label.getLayoutData()).heightHint = convertHeightInCharsToPixels(7);
((GridData) label.getLayoutData()).heightHint = convertHeightInCharsToPixels(1);
}
void updateRootDirectoryButtons() {
@ -307,7 +315,7 @@ public class PreferencesDialog extends Dialog {
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
pages.add("Assembler");
@ -453,7 +461,7 @@ public class PreferencesDialog extends Dialog {
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
pages.add("Editor");
@ -514,7 +522,7 @@ public class PreferencesDialog extends Dialog {
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
pages.add("Formatter");
@ -567,6 +575,143 @@ public class PreferencesDialog extends Dialog {
directivePrefix.select(preferences.getDirectivePrefix());
}
void createEmulatorPage(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = layout.marginWidth = 0;
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
pages.add("Emulator");
Label label = new Label(composite, SWT.NONE);
label.setText("ROM images");
Composite container = new Composite(composite, SWT.NONE);
layout = new GridLayout(3, false);
layout.marginWidth = layout.marginHeight = 0;
container.setLayout(layout);
container.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
romAddress1 = new Text(container, SWT.BORDER);
romAddress1.setLayoutData(new GridData(convertWidthInCharsToPixels(5), SWT.DEFAULT));
romAddress1.setText(String.format("%04X", preferences.getRomAddress1()));
romImage1 = new Text(container, SWT.BORDER);
romImage1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
if (preferences.getRomImage1() != null) {
romImage1.setText(preferences.getRomImage1());
}
Button button = new Button(container, SWT.PUSH);
button.setText("Browse");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog dlg = new FileDialog(getShell(), SWT.OPEN);
dlg.setText("Open ROM image");
dlg.setFilterNames(new String[] {
"All files",
"Rom images",
"Source files"
});
dlg.setFilterExtensions(new String[] {
"*.*",
"*.BIN;*.bin",
"*.ASM;*.asm"
});
dlg.setFilterIndex(1);
final String fileName = dlg.open();
if (fileName != null) {
romImage1.setText(fileName);
}
}
});
new Label(composite, SWT.NONE);
container = new Composite(composite, SWT.NONE);
layout = new GridLayout(3, false);
layout.marginWidth = layout.marginHeight = 0;
container.setLayout(layout);
container.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
romAddress2 = new Text(container, SWT.BORDER);
romAddress2.setLayoutData(new GridData(convertWidthInCharsToPixels(5), SWT.DEFAULT));
romAddress2.setText(String.format("%04X", preferences.getRomAddress2()));
romImage2 = new Text(container, SWT.BORDER);
romImage2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
if (preferences.getRomImage2() != null) {
romImage2.setText(preferences.getRomImage2());
}
button = new Button(container, SWT.PUSH);
button.setText("Browse");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog dlg = new FileDialog(getShell(), SWT.OPEN);
dlg.setText("Open ROM image");
dlg.setFilterNames(new String[] {
"All files",
"Rom images",
"Source files"
});
dlg.setFilterExtensions(new String[] {
"*.*",
"*.BIN;*.bin",
"*.ASM;*.asm"
});
dlg.setFilterIndex(1);
final String fileName = dlg.open();
if (fileName != null) {
romImage2.setText(fileName);
}
}
});
label = new Label(composite, SWT.NONE);
label.setText("CF card image");
container = new Composite(composite, SWT.NONE);
layout = new GridLayout(2, false);
layout.marginWidth = layout.marginHeight = 0;
container.setLayout(layout);
container.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
compactFlashImage = new Text(container, SWT.BORDER);
compactFlashImage.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
if (preferences.getCompactFlashImage() != null) {
compactFlashImage.setText(preferences.getCompactFlashImage());
}
button = new Button(container, SWT.PUSH);
button.setText("Browse");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog dlg = new FileDialog(getShell(), SWT.OPEN);
dlg.setText("Open Compact Flash image");
dlg.setFilterNames(new String[] {
"All files",
"Compact Flash images"
});
dlg.setFilterExtensions(new String[] {
"*.*",
"*.IMG;*.img"
});
dlg.setFilterIndex(1);
final String fileName = dlg.open();
if (fileName != null) {
compactFlashImage.setText(fileName);
}
}
});
}
void addSeparator(Composite parent) {
Label label = new Label(parent, SWT.NONE);
label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false, ((GridLayout) parent.getLayout()).numColumns, 1));
@ -598,6 +743,12 @@ public class PreferencesDialog extends Dialog {
preferences.setDownloadCommand(downloadCommand.getText());
preferences.setXmodemCommand(xmodemCommand.getText());
preferences.setRomAddress1(Integer.valueOf(romAddress1.getText(), 16));
preferences.setRomImage1(romImage1.getText());
preferences.setRomAddress2(Integer.valueOf(romAddress2.getText(), 16));
preferences.setRomImage2(romImage2.getText());
preferences.setCompactFlashImage(compactFlashImage.getText());
super.okPressed();
}
}

Wyświetl plik

@ -11,13 +11,12 @@ package z80core;
*/
public class MemIoOps {
private byte z80Ram[] = null;
private byte z80Ports[] = null;
private byte[] z80Ram;
private byte[] z80Ports;
private long tstates = 0;
public MemIoOps() {
z80Ram = new byte[0x10000];
z80Ports = new byte[0x10000];
}
public MemIoOps(int ramSize, int portSize) {
@ -42,11 +41,11 @@ public class MemIoOps {
return z80Ram;
}
public void setRam(byte ram[]) {
public void setRam(byte[] ram) {
z80Ram = ram;
}
public void setPorts(byte ports[]) {
public void setPorts(byte[] ports) {
z80Ram = ports;
}