Adding disassembly extract/view support.
This commit is contained in:
parent
0842f1f31f
commit
d19676fa9e
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* AppleCommander - An Apple ][ image utility.
|
||||||
|
* Copyright (C) 2019-2022 by Robert Greene and others
|
||||||
|
* robgreene at users.sourceforge.net
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
package io.github.applecommander.acx;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.webcodepro.applecommander.storage.FileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.AppleWorksDataBaseFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.AppleWorksSpreadSheetFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.AppleWorksWordProcessorFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.AssemblySourceFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.BinaryFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.BusinessBASICFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.DisassemblyFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.GutenbergFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.HexDumpFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
|
||||||
|
|
||||||
|
import io.github.applecommander.filters.AppleSingleFileFilter;
|
||||||
|
import io.github.applecommander.filters.RawFileFilter;
|
||||||
|
|
||||||
|
public enum ExportMethod {
|
||||||
|
APPLESINGLE(AppleSingleFileFilter::new, "as", "applesingle"),
|
||||||
|
APPLESOFT(ApplesoftFileFilter::new, "bas", "applesoft"),
|
||||||
|
APPLEWORKS_DATABASE(AppleWorksDataBaseFileFilter::new, "adb"),
|
||||||
|
APPLEWORKS_SPREADSHEET(AppleWorksSpreadSheetFileFilter::new, "asp"),
|
||||||
|
APPLEWORKS_WORDPROCESSOR(AppleWorksWordProcessorFileFilter::new, "awp"),
|
||||||
|
ASSEMBLY_SOURCE(AssemblySourceFileFilter::new, "asm", "assembly"),
|
||||||
|
BINARY(BinaryFileFilter::new, "bin", "binary"),
|
||||||
|
BUSINESS_BASIC(BusinessBASICFileFilter::new, "bbas", "business-basic"),
|
||||||
|
DISASSEMBLY(DisassemblyFileFilter::new, "disasm", "disassembly"),
|
||||||
|
GRAPHICS(GraphicsFileFilter::new, "gr", "graphics"),
|
||||||
|
GUTENBERG_FILE(GutenbergFileFilter::new, "gutenberg"),
|
||||||
|
HEX_DUMP(HexDumpFileFilter::new, "hex"),
|
||||||
|
INTEGER_BASIC(IntegerBasicFileFilter::new, "int", "integer"),
|
||||||
|
PASCAL_TEXT(PascalTextFileFilter::new, "ptext", "pascal-text"),
|
||||||
|
RAW(RawFileFilter::new, "raw"),
|
||||||
|
TEXT(TextFileFilter::new, "text");
|
||||||
|
|
||||||
|
private Supplier<FileFilter> constructor;
|
||||||
|
private List<String> codes;
|
||||||
|
|
||||||
|
private ExportMethod(Supplier<FileFilter> constructor, String... codes) {
|
||||||
|
this.constructor = constructor;
|
||||||
|
this.codes = Arrays.asList(codes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileFilter create() {
|
||||||
|
return constructor.get();
|
||||||
|
}
|
||||||
|
public List<String> getCodes() {
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,9 +39,10 @@ import com.webcodepro.applecommander.util.filestreamer.FileStreamer;
|
||||||
import com.webcodepro.applecommander.util.filestreamer.FileTuple;
|
import com.webcodepro.applecommander.util.filestreamer.FileTuple;
|
||||||
import com.webcodepro.applecommander.util.filestreamer.TypeOfFile;
|
import com.webcodepro.applecommander.util.filestreamer.TypeOfFile;
|
||||||
|
|
||||||
|
import io.github.applecommander.acx.ExportMethod;
|
||||||
import io.github.applecommander.acx.base.ReadOnlyDiskImageCommandOptions;
|
import io.github.applecommander.acx.base.ReadOnlyDiskImageCommandOptions;
|
||||||
import io.github.applecommander.filters.AppleSingleFileFilter;
|
import io.github.applecommander.acx.converter.ExportMethodConverter;
|
||||||
import io.github.applecommander.filters.RawFileFilter;
|
import io.github.applecommander.acx.converter.ExportMethodConverter.ExportMethodCandidates;
|
||||||
import picocli.CommandLine.ArgGroup;
|
import picocli.CommandLine.ArgGroup;
|
||||||
import picocli.CommandLine.Command;
|
import picocli.CommandLine.Command;
|
||||||
import picocli.CommandLine.Model.CommandSpec;
|
import picocli.CommandLine.Model.CommandSpec;
|
||||||
|
@ -143,13 +144,21 @@ public class ExportCommand extends ReadOnlyDiskImageCommandOptions {
|
||||||
private static class FileExtractMethods {
|
private static class FileExtractMethods {
|
||||||
private Function<FileEntry,FileFilter> extractFunction = this::asSuggestedFile;
|
private Function<FileEntry,FileFilter> extractFunction = this::asSuggestedFile;
|
||||||
|
|
||||||
|
@Option(names = { "--method" }, converter = ExportMethodConverter.class,
|
||||||
|
completionCandidates = ExportMethodCandidates.class,
|
||||||
|
description = "Select a specific export method type (${COMPLETION-CANDIDATES}).")
|
||||||
|
public void selectExportMethod(final ExportMethod exportMethod) {
|
||||||
|
this.extractFunction = fileFilter -> exportMethod.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Short-cuts to some of the more common, non-suggested, filters
|
||||||
@Option(names = { "--raw", "--binary" }, description = "Extract file in native format.")
|
@Option(names = { "--raw", "--binary" }, description = "Extract file in native format.")
|
||||||
public void setBinaryExtraction(boolean flag) {
|
public void setBinaryExtraction(boolean flag) {
|
||||||
this.extractFunction = this::asRawFile;
|
selectExportMethod(ExportMethod.BINARY);
|
||||||
}
|
}
|
||||||
@Option(names = { "--hex", "--dump" }, description = "Extract file in hex dump format.")
|
@Option(names = { "--hex", "--dump" }, description = "Extract file in hex dump format.")
|
||||||
public void setHexDumpExtraction(boolean flag) {
|
public void setHexDumpExtraction(boolean flag) {
|
||||||
this.extractFunction = this::asHexDumpFile;
|
selectExportMethod(ExportMethod.HEX_DUMP);
|
||||||
}
|
}
|
||||||
@Option(names = { "--suggested" }, description = "Extract file as suggested by AppleCommander (default)")
|
@Option(names = { "--suggested" }, description = "Extract file as suggested by AppleCommander (default)")
|
||||||
public void setSuggestedExtraction(boolean flag) {
|
public void setSuggestedExtraction(boolean flag) {
|
||||||
|
@ -157,12 +166,13 @@ public class ExportCommand extends ReadOnlyDiskImageCommandOptions {
|
||||||
}
|
}
|
||||||
@Option(names = { "--as", "--applesingle" }, description = "Extract file to AppleSingle file.")
|
@Option(names = { "--as", "--applesingle" }, description = "Extract file to AppleSingle file.")
|
||||||
public void setAppleSingleExtraction(boolean flag) {
|
public void setAppleSingleExtraction(boolean flag) {
|
||||||
this.extractFunction = this::asAppleSingleFile;
|
selectExportMethod(ExportMethod.APPLESINGLE);
|
||||||
|
}
|
||||||
|
@Option(names = { "--disassembly" }, description = "Dissassembly file.")
|
||||||
|
public void setDisassemblyExtraction(boolean flag) {
|
||||||
|
selectExportMethod(ExportMethod.DISASSEMBLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileFilter asRawFile(FileEntry entry) {
|
|
||||||
return new RawFileFilter();
|
|
||||||
}
|
|
||||||
public FileFilter asSuggestedFile(FileEntry entry) {
|
public FileFilter asSuggestedFile(FileEntry entry) {
|
||||||
FileFilter ff = entry.getSuggestedFilter();
|
FileFilter ff = entry.getSuggestedFilter();
|
||||||
if (ff instanceof BinaryFileFilter) {
|
if (ff instanceof BinaryFileFilter) {
|
||||||
|
@ -170,11 +180,5 @@ public class ExportCommand extends ReadOnlyDiskImageCommandOptions {
|
||||||
}
|
}
|
||||||
return ff;
|
return ff;
|
||||||
}
|
}
|
||||||
public FileFilter asHexDumpFile(FileEntry entry) {
|
|
||||||
return new HexDumpFileFilter();
|
|
||||||
}
|
|
||||||
public FileFilter asAppleSingleFile(FileEntry entry) {
|
|
||||||
return new AppleSingleFileFilter();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* AppleCommander - An Apple ][ image utility.
|
||||||
|
* Copyright (C) 2019-2022 by Robert Greene and others
|
||||||
|
* robgreene at users.sourceforge.net
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
package io.github.applecommander.acx.converter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.github.applecommander.acx.ExportMethod;
|
||||||
|
import picocli.CommandLine.ITypeConverter;
|
||||||
|
import picocli.CommandLine.TypeConversionException;
|
||||||
|
|
||||||
|
public class ExportMethodConverter implements ITypeConverter<ExportMethod> {
|
||||||
|
public static final Map<String,ExportMethod> EXPORTS = new HashMap<>();
|
||||||
|
static {
|
||||||
|
for (ExportMethod x : ExportMethod.values()) {
|
||||||
|
for (String code : x.getCodes()) {
|
||||||
|
EXPORTS.put(code, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExportMethod convert(String value) throws Exception {
|
||||||
|
if (EXPORTS.containsKey(value)) {
|
||||||
|
return EXPORTS.get(value);
|
||||||
|
}
|
||||||
|
throw new TypeConversionException(String.format("Export method not found: %s", value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ExportMethodCandidates extends ArrayList<String> {
|
||||||
|
private static final long serialVersionUID = -744232190636905235L;
|
||||||
|
|
||||||
|
ExportMethodCandidates() {
|
||||||
|
super(EXPORTS.keySet());
|
||||||
|
Collections.sort(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,3 +16,4 @@ commonsCsvVersion=1.8
|
||||||
gsonVersion=2.8.6
|
gsonVersion=2.8.6
|
||||||
picocliVersion=4.6.2
|
picocliVersion=4.6.2
|
||||||
springBoot=2.6.1
|
springBoot=2.6.1
|
||||||
|
acdasmVersion=0.3.0
|
||||||
|
|
|
@ -16,6 +16,7 @@ repositories {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "net.sf.applecommander:ShrinkItArchive:$shkVersion"
|
implementation "net.sf.applecommander:ShrinkItArchive:$shkVersion"
|
||||||
|
implementation "net.sf.applecommander:acdasm:$acdasmVersion"
|
||||||
implementation "org.apache.commons:commons-csv:$commonsCsvVersion"
|
implementation "org.apache.commons:commons-csv:$commonsCsvVersion"
|
||||||
implementation "com.google.code.gson:gson:$gsonVersion"
|
implementation "com.google.code.gson:gson:$gsonVersion"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* AppleCommander - An Apple ][ image utility.
|
||||||
|
* Copyright (C) 2002-2022 by Robert Greene
|
||||||
|
* robgreene at users.sourceforge.net
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
package com.webcodepro.applecommander.storage.filters;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.webcodepro.applecommander.storage.FileEntry;
|
||||||
|
import com.webcodepro.applecommander.storage.FileFilter;
|
||||||
|
|
||||||
|
import io.github.applecommander.disassembler.api.Disassembler;
|
||||||
|
import io.github.applecommander.disassembler.api.Instruction;
|
||||||
|
import io.github.applecommander.disassembler.api.mos6502.InstructionSet6502;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disassemble the given set of bytes.
|
||||||
|
*/
|
||||||
|
public class DisassemblyFileFilter implements FileFilter {
|
||||||
|
public byte[] filter(FileEntry fileEntry) {
|
||||||
|
List<Instruction> instructions = Disassembler.with(fileEntry.getFileData())
|
||||||
|
.startingAddress(fileEntry.getAddress())
|
||||||
|
.use(InstructionSet6502.for6502())
|
||||||
|
.decode();
|
||||||
|
|
||||||
|
String code = instructions.stream()
|
||||||
|
.map(this::emitRaw)
|
||||||
|
.collect(Collectors.joining());
|
||||||
|
|
||||||
|
return code.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuggestedFileName(FileEntry fileEntry) {
|
||||||
|
String fileName = fileEntry.getFilename().trim();
|
||||||
|
if (!fileName.toLowerCase().endsWith(".asm")) {
|
||||||
|
fileName = fileName + ".asm";
|
||||||
|
}
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String emitRaw(Instruction instruction) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
pw.printf("%04X- ", instruction.getAddress());
|
||||||
|
|
||||||
|
byte[] code = instruction.getBytes();
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
|
if (i >= code.length) {
|
||||||
|
pw.printf(" ");
|
||||||
|
} else {
|
||||||
|
pw.printf("%02X ", code[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pw.printf(" %s\n", instruction.formatOperandWithValue());
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.AssemblySourceFileFilter;
|
import com.webcodepro.applecommander.storage.filters.AssemblySourceFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.BinaryFileFilter;
|
import com.webcodepro.applecommander.storage.filters.BinaryFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.BusinessBASICFileFilter;
|
import com.webcodepro.applecommander.storage.filters.BusinessBASICFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.DisassemblyFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
|
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
|
||||||
|
@ -589,6 +590,8 @@ public class ProdosFileEntry extends ProdosCommonEntry implements FileEntry {
|
||||||
filter.setMode(GraphicsFileFilter.MODE_QUICKDRAW2_ICON);
|
filter.setMode(GraphicsFileFilter.MODE_QUICKDRAW2_ICON);
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
case 0xff:
|
||||||
|
return new DisassemblyFileFilter();
|
||||||
}
|
}
|
||||||
return new BinaryFileFilter();
|
return new BinaryFileFilter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,6 +351,9 @@ FileViewerWindow.RawDumpTooltip=Displays file as a raw hex dump (F4)
|
||||||
FileViewerWindow.CopyButton=Copy
|
FileViewerWindow.CopyButton=Copy
|
||||||
FileViewerWindow.CopyTooltip=Copies selection to the clipboard (CTRL+C)
|
FileViewerWindow.CopyTooltip=Copies selection to the clipboard (CTRL+C)
|
||||||
FileViewerWindow.PrintTooltip=Print contents... (CTRL+P)
|
FileViewerWindow.PrintTooltip=Print contents... (CTRL+P)
|
||||||
|
FileViewerWindow.DisassemblyButton=Disassembly
|
||||||
|
FileViewerWindow.DisassemblyTooltip=Displays file disassembled
|
||||||
|
|
||||||
|
|
||||||
# DiskWindow
|
# DiskWindow
|
||||||
DiskWindow.Title=AppleCommander Disk View - {0}
|
DiskWindow.Title=AppleCommander Disk View - {0}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.junit.Test;
|
||||||
import com.webcodepro.applecommander.storage.FormattedDisk.DiskUsage;
|
import com.webcodepro.applecommander.storage.FormattedDisk.DiskUsage;
|
||||||
import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
|
import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.BinaryFileFilter;
|
import com.webcodepro.applecommander.storage.filters.BinaryFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.DisassemblyFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
|
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
|
||||||
|
@ -69,7 +70,7 @@ public class DiskHelperTest {
|
||||||
FormattedDisk[] disks = showDirectory(config.getDiskDir() + "/Prodos.dsk"); //$NON-NLS-1$
|
FormattedDisk[] disks = showDirectory(config.getDiskDir() + "/Prodos.dsk"); //$NON-NLS-1$
|
||||||
assertApplesoftFile(disks[0], "COPY.ME"); //$NON-NLS-1$
|
assertApplesoftFile(disks[0], "COPY.ME"); //$NON-NLS-1$
|
||||||
assertBinaryFile(disks[0], "SETTINGS"); //$NON-NLS-1$
|
assertBinaryFile(disks[0], "SETTINGS"); //$NON-NLS-1$
|
||||||
assertBinaryFile(disks[0], "PRODOS"); //$NON-NLS-1$
|
assertDisassemblyFile(disks[0], "PRODOS"); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -233,6 +234,14 @@ public class DiskHelperTest {
|
||||||
fileEntry.getSuggestedFilter() instanceof BinaryFileFilter);
|
fileEntry.getSuggestedFilter() instanceof BinaryFileFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void assertDisassemblyFile(FormattedDisk disk, String filename) throws DiskException {
|
||||||
|
assertNotNull(filename + " test: Disk should not be null", disk);
|
||||||
|
FileEntry fileEntry = disk.getFile(filename);
|
||||||
|
assertNotNull(filename + " test: File not found", disk);
|
||||||
|
assertTrue("DisassemblyFileFilter was not chosen",
|
||||||
|
fileEntry.getSuggestedFilter() instanceof DisassemblyFileFilter);
|
||||||
|
}
|
||||||
|
|
||||||
protected void assertGraphicsFile(FormattedDisk disk, String filename) throws DiskException {
|
protected void assertGraphicsFile(FormattedDisk disk, String filename) throws DiskException {
|
||||||
assertNotNull(filename + " test: Disk should not be null", disk); //$NON-NLS-1$
|
assertNotNull(filename + " test: Disk should not be null", disk); //$NON-NLS-1$
|
||||||
FileEntry fileEntry = disk.getFile(filename);
|
FileEntry fileEntry = disk.getFile(filename);
|
||||||
|
|
|
@ -21,6 +21,7 @@ package com.webcodepro.applecommander.ui.swt;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.custom.ScrolledComposite;
|
import org.eclipse.swt.custom.ScrolledComposite;
|
||||||
|
@ -48,6 +49,7 @@ import com.webcodepro.applecommander.storage.filters.AppleWorksWordProcessorFile
|
||||||
import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
|
import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.AssemblySourceFileFilter;
|
import com.webcodepro.applecommander.storage.filters.AssemblySourceFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.BusinessBASICFileFilter;
|
import com.webcodepro.applecommander.storage.filters.BusinessBASICFileFilter;
|
||||||
|
import com.webcodepro.applecommander.storage.filters.DisassemblyFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
||||||
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
|
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
|
||||||
|
@ -56,6 +58,7 @@ import com.webcodepro.applecommander.storage.filters.GutenbergFileFilter;
|
||||||
import com.webcodepro.applecommander.ui.UiBundle;
|
import com.webcodepro.applecommander.ui.UiBundle;
|
||||||
import com.webcodepro.applecommander.ui.swt.filteradapter.ApplesoftFilterAdapter;
|
import com.webcodepro.applecommander.ui.swt.filteradapter.ApplesoftFilterAdapter;
|
||||||
import com.webcodepro.applecommander.ui.swt.filteradapter.BusinessBASICFilterAdapter;
|
import com.webcodepro.applecommander.ui.swt.filteradapter.BusinessBASICFilterAdapter;
|
||||||
|
import com.webcodepro.applecommander.ui.swt.filteradapter.DisassemblyFilterAdapter;
|
||||||
import com.webcodepro.applecommander.ui.swt.filteradapter.FilterAdapter;
|
import com.webcodepro.applecommander.ui.swt.filteradapter.FilterAdapter;
|
||||||
import com.webcodepro.applecommander.ui.swt.filteradapter.GraphicsFilterAdapter;
|
import com.webcodepro.applecommander.ui.swt.filteradapter.GraphicsFilterAdapter;
|
||||||
import com.webcodepro.applecommander.ui.swt.filteradapter.HexFilterAdapter;
|
import com.webcodepro.applecommander.ui.swt.filteradapter.HexFilterAdapter;
|
||||||
|
@ -90,6 +93,7 @@ public class FileViewerWindow {
|
||||||
private ToolBar toolBar;
|
private ToolBar toolBar;
|
||||||
private ToolItem nativeToolItem;
|
private ToolItem nativeToolItem;
|
||||||
private ToolItem hexDumpToolItem;
|
private ToolItem hexDumpToolItem;
|
||||||
|
private Optional<ToolItem> disassemblyToolItem = Optional.empty(); // May or may not be setup
|
||||||
private ToolItem rawDumpToolItem;
|
private ToolItem rawDumpToolItem;
|
||||||
private ToolItem copyToolItem;
|
private ToolItem copyToolItem;
|
||||||
|
|
||||||
|
@ -103,6 +107,7 @@ public class FileViewerWindow {
|
||||||
private FilterAdapter nativeFilterAdapter;
|
private FilterAdapter nativeFilterAdapter;
|
||||||
private FilterAdapter hexFilterAdapter;
|
private FilterAdapter hexFilterAdapter;
|
||||||
private FilterAdapter rawDumpFilterAdapter;
|
private FilterAdapter rawDumpFilterAdapter;
|
||||||
|
private FilterAdapter disassemblyFilterAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the file viewer window.
|
* Construct the file viewer window.
|
||||||
|
@ -222,6 +227,11 @@ public class FileViewerWindow {
|
||||||
textBundle.get("FileViewerWindow.TextTooltip"), //$NON-NLS-1$
|
textBundle.get("FileViewerWindow.TextTooltip"), //$NON-NLS-1$
|
||||||
imageManager.get(ImageManager.ICON_VIEW_AS_TEXTFILE)
|
imageManager.get(ImageManager.ICON_VIEW_AS_TEXTFILE)
|
||||||
));
|
));
|
||||||
|
nativeFilterAdapterMap.put(DisassemblyFileFilter.class,
|
||||||
|
new DisassemblyFilterAdapter(this, textBundle.get("FileViewerWindow.DisassemblyButton"),
|
||||||
|
textBundle.get("FileViewerWindow.DisassemblyTooltip"),
|
||||||
|
imageManager.get(ImageManager.ICON_COMPILE_FILE)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,6 +271,10 @@ public class FileViewerWindow {
|
||||||
nativeFilterAdapter = hexFilterAdapter;
|
nativeFilterAdapter = hexFilterAdapter;
|
||||||
}
|
}
|
||||||
rawDumpToolItem = createRawDumpToolItem();
|
rawDumpToolItem = createRawDumpToolItem();
|
||||||
|
// Add the disassembly button only if it's not the default and if this filetype has a start address.
|
||||||
|
if (fileEntry != null && fileEntry.needsAddress() && !(nativeFilter instanceof DisassemblyFileFilter)) {
|
||||||
|
disassemblyToolItem = Optional.of(createDisassemblyToolItem());
|
||||||
|
}
|
||||||
new ToolItem(toolBar, SWT.SEPARATOR);
|
new ToolItem(toolBar, SWT.SEPARATOR);
|
||||||
copyToolItem = createCopyToolItem();
|
copyToolItem = createCopyToolItem();
|
||||||
new ToolItem(toolBar, SWT.SEPARATOR);
|
new ToolItem(toolBar, SWT.SEPARATOR);
|
||||||
|
@ -291,7 +305,19 @@ public class FileViewerWindow {
|
||||||
ToolItem toolItem = rawDumpFilterAdapter.create(toolBar);
|
ToolItem toolItem = rawDumpFilterAdapter.create(toolBar);
|
||||||
return toolItem;
|
return toolItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the disassembly tool item (button).
|
||||||
|
*/
|
||||||
|
protected ToolItem createDisassemblyToolItem() {
|
||||||
|
disassemblyFilterAdapter = new DisassemblyFilterAdapter(this, textBundle.get("FileViewerWindow.DisassemblyButton"), //$NON-NLS-1$
|
||||||
|
textBundle.get("FileViewerWindow.DisassemblyTooltip"), //$NON-NLS-1$
|
||||||
|
imageManager.get(ImageManager.ICON_COMPILE_FILE));
|
||||||
|
disassemblyFilterAdapter.setDisassemblySelected();
|
||||||
|
ToolItem toolItem = disassemblyFilterAdapter.create(toolBar);
|
||||||
|
return toolItem;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the copy tool item (button).
|
* Create the copy tool item (button).
|
||||||
*/
|
*/
|
||||||
|
@ -351,15 +377,15 @@ public class FileViewerWindow {
|
||||||
switch (event.keyCode) {
|
switch (event.keyCode) {
|
||||||
case SWT.F2: // the "native" file format (image, text, etc)
|
case SWT.F2: // the "native" file format (image, text, etc)
|
||||||
getNativeFilterAdapter().display();
|
getNativeFilterAdapter().display();
|
||||||
setFilterToolItemSelection(true, false, false);
|
setFilterToolItemSelection(true, false, false, false);
|
||||||
break;
|
break;
|
||||||
case SWT.F3: // Hex format
|
case SWT.F3: // Hex format
|
||||||
getHexFilterAdapter().display();
|
getHexFilterAdapter().display();
|
||||||
setFilterToolItemSelection(false, true, false);
|
setFilterToolItemSelection(false, true, false, false);
|
||||||
break;
|
break;
|
||||||
case SWT.F4: // "Raw" hex format
|
case SWT.F4: // "Raw" hex format
|
||||||
getRawDumpFilterAdapter().display();
|
getRawDumpFilterAdapter().display();
|
||||||
setFilterToolItemSelection(false, false, true);
|
setFilterToolItemSelection(false, false, true, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,10 +421,11 @@ public class FileViewerWindow {
|
||||||
public Color getBlueColor() {
|
public Color getBlueColor() {
|
||||||
return blue;
|
return blue;
|
||||||
}
|
}
|
||||||
public void setFilterToolItemSelection(boolean nativeSelected, boolean hexSelected, boolean dumpSelected) {
|
public void setFilterToolItemSelection(boolean nativeSelected, boolean hexSelected, boolean dumpSelected, boolean disassemblySelected) {
|
||||||
if (nativeToolItem != null) nativeToolItem.setSelection(nativeSelected);
|
if (nativeToolItem != null) nativeToolItem.setSelection(nativeSelected);
|
||||||
hexDumpToolItem.setSelection(hexSelected);
|
hexDumpToolItem.setSelection(hexSelected);
|
||||||
rawDumpToolItem.setSelection(dumpSelected);
|
rawDumpToolItem.setSelection(dumpSelected);
|
||||||
|
disassemblyToolItem.ifPresent(toolItem -> toolItem.setSelection(disassemblySelected));
|
||||||
}
|
}
|
||||||
protected ContentTypeAdapter getContentTypeAdapter() {
|
protected ContentTypeAdapter getContentTypeAdapter() {
|
||||||
return contentTypeAdapter;
|
return contentTypeAdapter;
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* AppleCommander - An Apple ][ image utility.
|
||||||
|
* Copyright (C) 2002-2022 by Robert Greene
|
||||||
|
* robgreene at users.sourceforge.net
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
package com.webcodepro.applecommander.ui.swt.filteradapter;
|
||||||
|
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
|
||||||
|
import com.webcodepro.applecommander.storage.filters.DisassemblyFileFilter;
|
||||||
|
import com.webcodepro.applecommander.ui.swt.FileViewerWindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a view of the dissasembly of a program as seen when loaded from the disk.
|
||||||
|
*
|
||||||
|
* @author Rob Greene
|
||||||
|
*/
|
||||||
|
public class DisassemblyFilterAdapter extends TextFilterAdapter {
|
||||||
|
public DisassemblyFilterAdapter(FileViewerWindow window, String text, String toolTipText, Image image) {
|
||||||
|
super(window, text, toolTipText, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String createTextContent() {
|
||||||
|
return new String(new DisassemblyFileFilter().filter(getFileEntry()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,6 +50,7 @@ public abstract class FilterAdapter {
|
||||||
private boolean nativeSelected = true;
|
private boolean nativeSelected = true;
|
||||||
private boolean hexSelected = false;
|
private boolean hexSelected = false;
|
||||||
private boolean dumpSelected = false;
|
private boolean dumpSelected = false;
|
||||||
|
private boolean disassemblySelected = false;
|
||||||
|
|
||||||
public FilterAdapter(FileViewerWindow window, String text, String toolTipText,
|
public FilterAdapter(FileViewerWindow window, String text, String toolTipText,
|
||||||
Image image) {
|
Image image) {
|
||||||
|
@ -77,7 +78,7 @@ public abstract class FilterAdapter {
|
||||||
public void widgetSelected(SelectionEvent e) {
|
public void widgetSelected(SelectionEvent e) {
|
||||||
display();
|
display();
|
||||||
getWindow().setFilterToolItemSelection(
|
getWindow().setFilterToolItemSelection(
|
||||||
isNativeSelected(), isHexSelected(), isDumpSelected());
|
isNativeSelected(), isHexSelected(), isDumpSelected(), isDisassemblySelected());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -130,16 +131,25 @@ public abstract class FilterAdapter {
|
||||||
nativeSelected = false;
|
nativeSelected = false;
|
||||||
hexSelected = false;
|
hexSelected = false;
|
||||||
dumpSelected = true;
|
dumpSelected = true;
|
||||||
|
disassemblySelected = false;
|
||||||
}
|
}
|
||||||
public void setHexSelected() {
|
public void setHexSelected() {
|
||||||
nativeSelected = false;
|
nativeSelected = false;
|
||||||
hexSelected = true;
|
hexSelected = true;
|
||||||
dumpSelected = false;
|
dumpSelected = false;
|
||||||
|
disassemblySelected = false;
|
||||||
}
|
}
|
||||||
|
public void setDisassemblySelected() {
|
||||||
|
nativeSelected = false;
|
||||||
|
hexSelected = false;
|
||||||
|
dumpSelected = false;
|
||||||
|
disassemblySelected = true;
|
||||||
|
}
|
||||||
public void setNativeSelected() {
|
public void setNativeSelected() {
|
||||||
nativeSelected = true;
|
nativeSelected = true;
|
||||||
hexSelected = false;
|
hexSelected = false;
|
||||||
dumpSelected = false;
|
dumpSelected = false;
|
||||||
|
disassemblySelected = false;
|
||||||
}
|
}
|
||||||
protected boolean isDumpSelected() {
|
protected boolean isDumpSelected() {
|
||||||
return dumpSelected;
|
return dumpSelected;
|
||||||
|
@ -147,6 +157,9 @@ public abstract class FilterAdapter {
|
||||||
protected boolean isHexSelected() {
|
protected boolean isHexSelected() {
|
||||||
return hexSelected;
|
return hexSelected;
|
||||||
}
|
}
|
||||||
|
protected boolean isDisassemblySelected() {
|
||||||
|
return disassemblySelected;
|
||||||
|
}
|
||||||
protected boolean isNativeSelected() {
|
protected boolean isNativeSelected() {
|
||||||
return nativeSelected;
|
return nativeSelected;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue