mirror of
https://github.com/markdavidlong/AppleSAWS.git
synced 2025-05-19 21:38:16 +00:00
New IntBasic file viewer, various code clean up and bug fixes.
This commit is contained in:
parent
e353df7232
commit
a30eaec4c0
292
AppleSAWS.pro
292
AppleSAWS.pro
@ -1,143 +1,149 @@
|
||||
|
||||
QT += core gui printsupport
|
||||
CONFIG += c++11
|
||||
|
||||
MOC_DIR = ./.build
|
||||
UI_DIR = ./.build
|
||||
OBJECTS_DIR = ./.build
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = AppleSAWS
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += src/
|
||||
INCLUDEPATH += src/relocatablefile
|
||||
INCLUDEPATH += src/diskfiles
|
||||
INCLUDEPATH += src/diskfiles/dos33
|
||||
INCLUDEPATH += src/util
|
||||
INCLUDEPATH += src/applesoftfile
|
||||
INCLUDEPATH += src/binaryfile
|
||||
INCLUDEPATH += src/textfile
|
||||
INCLUDEPATH += src/ui/viewers
|
||||
INCLUDEPATH += src/imported
|
||||
INCLUDEPATH += src/internals
|
||||
INCLUDEPATH += src/ui/diskexplorer/
|
||||
INCLUDEPATH += src/ui/widgets/
|
||||
INCLUDEPATH += src/ui
|
||||
|
||||
DEFINES += WS_VIDEO
|
||||
|
||||
SOURCES += \
|
||||
src/main.cpp \
|
||||
src/diskfiles/dos33/diskfile.cxx \
|
||||
src/diskfiles/dos33/sector.cxx \
|
||||
src/diskfiles/dos33/vtoc.cxx \
|
||||
src/diskfiles/dos33/catalogsector.cxx \
|
||||
src/diskfiles/dos33/tracksectorlist.cxx \
|
||||
src/diskfiles/dos33/filedescriptiveentry.cxx \
|
||||
src/diskfiles/dos33/genericfile.cxx \
|
||||
src/util/applestring.cxx \
|
||||
src/applesoftfile/applesoftfile.cxx \
|
||||
src/applesoftfile/applesofttoken.cxx \
|
||||
src/applesoftfile/applesoftformatter.cxx \
|
||||
src/binaryfile/disassembler.cxx \
|
||||
src/binaryfile/binaryfile.cxx \
|
||||
src/textfile/textfile.cxx \
|
||||
src/ui/catalogwidget.cxx \
|
||||
src/ui/viewers/hiresviewwidget.cxx \
|
||||
src/ui/viewers/applesoftfileviewer.cxx \
|
||||
src/ui/viewers/disassemblerviewer.cpp \
|
||||
src/ui/viewers/hexdumpviewer.cpp \
|
||||
src/ui/viewers/texthexdumpviewer.cpp \
|
||||
src/ui/viewers/mazeviewer.cpp \
|
||||
src/ui/viewers/charsetviewer.cpp \
|
||||
src/internals/memory.cxx \
|
||||
src/relocatablefile/relocatablefile.cxx \
|
||||
src/binaryfile/binaryfilemetadata.cpp \
|
||||
src/util/charset.cpp \
|
||||
src/ui/widgets/characterwidget.cpp \
|
||||
src/ui/viewers/applesoftfiledetailviewer.cpp \
|
||||
src/ui/widgets/hexconverter.cpp \
|
||||
src/ui/viewers/viewerbase.cpp \
|
||||
src/ui/widgets/CharacterSetExplorer.cpp \
|
||||
src/ui/widgets/HiresScreenWidget.cpp \
|
||||
src/ui/widgets/DisassemblerMetadataDialog.cpp \
|
||||
src/binaryfile/EntryPointModel.cpp \
|
||||
src/ui/widgets/LocationInfoDialog.cpp \
|
||||
src/binaryfile/EntryPoints.cpp \
|
||||
src/binaryfile/AssemblerSymbols.cpp \
|
||||
src/binaryfile/AssemblerSymbolModel.cpp \
|
||||
src/ui/diskexplorer/DiskExplorer.cpp \
|
||||
src/ui/diskexplorer/DiskExplorerMapWidget.cpp \
|
||||
src/applesoftfile/ApplesoftRetokenizer.cpp \
|
||||
src/internals/JumpLineManager.cpp \
|
||||
src/ui/widgets/FlowLineTextBrowser.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
src/diskfiles/dos33/diskfile.h \
|
||||
src/diskfiles/dos33/sector.h \
|
||||
src/diskfiles/dos33/vtoc.h \
|
||||
src/diskfiles/dos33/catalogsector.h \
|
||||
src/diskfiles/dos33/tracksectorlist.h \
|
||||
src/diskfiles/dos33/filedescriptiveentry.h \
|
||||
src/diskfiles/dos33/genericfile.h \
|
||||
src/util/util.h \
|
||||
src/util/applestring.h \
|
||||
src/applesoftfile/applesoftfile.h \
|
||||
src/applesoftfile/applesofttoken.h \
|
||||
src/binaryfile/disassembler.h \
|
||||
src/binaryfile/binaryfile.h \
|
||||
src/textfile/textfile.h \
|
||||
src/ui/catalogwidget.h \
|
||||
src/ui/viewers/hiresviewwidget.h \
|
||||
src/ui/viewers/applesoftfileviewer.h \
|
||||
src/applesoftfile/applesoftformatter.h \
|
||||
src/applesoftfile/applesoftline.h \
|
||||
src/internals/memory.h \
|
||||
src/ui/viewers/disassemblerviewer.h \
|
||||
src/ui/viewers/hexdumpviewer.h \
|
||||
src/ui/viewers/texthexdumpviewer.h \
|
||||
src/relocatablefile/relocatablefile.h \
|
||||
src/ui/viewers/mazeviewer.h \
|
||||
src/binaryfile/binaryfilemetadata.h \
|
||||
src/ui/widgets/characterwidget.h \
|
||||
src/util/charset.h \
|
||||
src/ui/viewers/charsetviewer.h \
|
||||
src/ui/viewers/applesoftfiledetailviewer.h \
|
||||
src/ui/widgets/hexconverter.h \
|
||||
src/ui/widgets/hrcgcontrolsinfo.h \
|
||||
src/ui/viewers/viewerbase.h \
|
||||
src/ui/viewers/fileviewerinterface.h \
|
||||
src/ui/widgets/CharacterSetExplorer.h \
|
||||
src/ui/widgets/HiresScreenWidget.h \
|
||||
src/ui/widgets/DisassemblerMetadataDialog.h \
|
||||
src/binaryfile/EntryPointModel.h \
|
||||
src/ui/widgets/LocationInfoDialog.h \
|
||||
src/binaryfile/EntryPoints.h \
|
||||
src/binaryfile/AssemblerSymbols.h \
|
||||
src/binaryfile/AssemblerSymbolModel.h \
|
||||
src/binaryfile/MemoryUsageMap.h \
|
||||
src/ui/diskexplorer/DiskExplorer.h \
|
||||
src/ui/diskexplorer/DiskExplorerMapWidget.h \
|
||||
src/applesoftfile/ApplesoftRetokenizer.h \
|
||||
src/util/AppleColors.h \
|
||||
src/internals/JumpLineManager.h \
|
||||
src/ui/widgets/FlowLineTextBrowser.h \
|
||||
src/ui/widgets/asciiinfodialog.h
|
||||
|
||||
FORMS += \
|
||||
src/ui/catalogwidget.ui \
|
||||
src/ui/viewers/applesoftfileviewer.ui \
|
||||
src/ui/viewers/disassemblerviewer.ui \
|
||||
src/ui/viewers/hexdumpviewer.ui \
|
||||
src/ui/viewers/texthexdumpviewer.ui \
|
||||
src/ui/viewers/applesoftfiledetailviewer.ui \
|
||||
src/ui/widgets/hexconverter.ui \
|
||||
src/ui/widgets/hrcgcontrolsinfo.ui \
|
||||
src/ui/viewers/viewerbase.ui \
|
||||
src/ui/widgets/CharacterSetExplorer.ui \
|
||||
src/ui/widgets/DisassemblerMetadataDialog.ui \
|
||||
src/ui/widgets/LocationInfoDialog.ui \
|
||||
src/ui/widgets/asciiinfodialog.ui
|
||||
|
||||
QT += core gui printsupport
|
||||
CONFIG += c++11
|
||||
|
||||
MOC_DIR = ./.build
|
||||
UI_DIR = ./.build
|
||||
OBJECTS_DIR = ./.build
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = AppleSAWS
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += src/
|
||||
INCLUDEPATH += src/relocatablefile
|
||||
INCLUDEPATH += src/diskfiles
|
||||
INCLUDEPATH += src/diskfiles/dos33
|
||||
INCLUDEPATH += src/util
|
||||
INCLUDEPATH += src/applesoftfile
|
||||
INCLUDEPATH += src/intbasic
|
||||
INCLUDEPATH += src/binaryfile
|
||||
INCLUDEPATH += src/textfile
|
||||
INCLUDEPATH += src/ui/viewers
|
||||
INCLUDEPATH += src/imported
|
||||
INCLUDEPATH += src/internals
|
||||
INCLUDEPATH += src/ui/diskexplorer/
|
||||
INCLUDEPATH += src/ui/widgets/
|
||||
INCLUDEPATH += src/ui
|
||||
|
||||
DEFINES += WS_VIDEO
|
||||
|
||||
SOURCES += \
|
||||
src/intbasic/IntBasicFile.cxx \
|
||||
src/main.cpp \
|
||||
src/diskfiles/dos33/diskfile.cxx \
|
||||
src/diskfiles/dos33/sector.cxx \
|
||||
src/diskfiles/dos33/vtoc.cxx \
|
||||
src/diskfiles/dos33/catalogsector.cxx \
|
||||
src/diskfiles/dos33/tracksectorlist.cxx \
|
||||
src/diskfiles/dos33/filedescriptiveentry.cxx \
|
||||
src/diskfiles/dos33/genericfile.cxx \
|
||||
src/ui/viewers/intbasicfileviewer.cxx \
|
||||
src/util/applestring.cxx \
|
||||
src/applesoftfile/applesoftfile.cxx \
|
||||
src/applesoftfile/applesofttoken.cxx \
|
||||
src/applesoftfile/applesoftformatter.cxx \
|
||||
src/binaryfile/disassembler.cxx \
|
||||
src/binaryfile/binaryfile.cxx \
|
||||
src/textfile/textfile.cxx \
|
||||
src/ui/catalogwidget.cxx \
|
||||
src/ui/viewers/hiresviewwidget.cxx \
|
||||
src/ui/viewers/applesoftfileviewer.cxx \
|
||||
src/ui/viewers/disassemblerviewer.cpp \
|
||||
src/ui/viewers/hexdumpviewer.cpp \
|
||||
src/ui/viewers/texthexdumpviewer.cpp \
|
||||
src/ui/viewers/mazeviewer.cpp \
|
||||
src/ui/viewers/charsetviewer.cpp \
|
||||
src/internals/memory.cxx \
|
||||
src/relocatablefile/relocatablefile.cxx \
|
||||
src/binaryfile/binaryfilemetadata.cpp \
|
||||
src/util/charset.cpp \
|
||||
src/ui/widgets/characterwidget.cpp \
|
||||
src/ui/viewers/applesoftfiledetailviewer.cpp \
|
||||
src/ui/widgets/hexconverter.cpp \
|
||||
src/ui/viewers/viewerbase.cpp \
|
||||
src/ui/widgets/CharacterSetExplorer.cpp \
|
||||
src/ui/widgets/HiresScreenWidget.cpp \
|
||||
src/ui/widgets/DisassemblerMetadataDialog.cpp \
|
||||
src/binaryfile/EntryPointModel.cpp \
|
||||
src/ui/widgets/LocationInfoDialog.cpp \
|
||||
src/binaryfile/EntryPoints.cpp \
|
||||
src/binaryfile/AssemblerSymbols.cpp \
|
||||
src/binaryfile/AssemblerSymbolModel.cpp \
|
||||
src/ui/diskexplorer/DiskExplorer.cpp \
|
||||
src/ui/diskexplorer/DiskExplorerMapWidget.cpp \
|
||||
src/applesoftfile/ApplesoftRetokenizer.cpp \
|
||||
src/internals/JumpLineManager.cpp \
|
||||
src/ui/widgets/FlowLineTextBrowser.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
src/diskfiles/dos33/diskfile.h \
|
||||
src/diskfiles/dos33/sector.h \
|
||||
src/diskfiles/dos33/vtoc.h \
|
||||
src/diskfiles/dos33/catalogsector.h \
|
||||
src/diskfiles/dos33/tracksectorlist.h \
|
||||
src/diskfiles/dos33/filedescriptiveentry.h \
|
||||
src/diskfiles/dos33/genericfile.h \
|
||||
src/intbasic/IntBasicFile.h \
|
||||
src/ui/viewers/intbasicfileviewer.h \
|
||||
src/util/util.h \
|
||||
src/util/applestring.h \
|
||||
src/applesoftfile/applesoftfile.h \
|
||||
src/applesoftfile/applesofttoken.h \
|
||||
src/binaryfile/disassembler.h \
|
||||
src/binaryfile/binaryfile.h \
|
||||
src/textfile/textfile.h \
|
||||
src/ui/catalogwidget.h \
|
||||
src/ui/viewers/hiresviewwidget.h \
|
||||
src/ui/viewers/applesoftfileviewer.h \
|
||||
src/applesoftfile/applesoftformatter.h \
|
||||
src/applesoftfile/applesoftline.h \
|
||||
src/internals/memory.h \
|
||||
src/ui/viewers/disassemblerviewer.h \
|
||||
src/ui/viewers/hexdumpviewer.h \
|
||||
src/ui/viewers/texthexdumpviewer.h \
|
||||
src/relocatablefile/relocatablefile.h \
|
||||
src/ui/viewers/mazeviewer.h \
|
||||
src/binaryfile/binaryfilemetadata.h \
|
||||
src/ui/widgets/characterwidget.h \
|
||||
src/util/charset.h \
|
||||
src/ui/viewers/charsetviewer.h \
|
||||
src/ui/viewers/applesoftfiledetailviewer.h \
|
||||
src/ui/widgets/hexconverter.h \
|
||||
src/ui/widgets/hrcgcontrolsinfo.h \
|
||||
src/ui/viewers/viewerbase.h \
|
||||
src/ui/viewers/fileviewerinterface.h \
|
||||
src/ui/widgets/CharacterSetExplorer.h \
|
||||
src/ui/widgets/HiresScreenWidget.h \
|
||||
src/ui/widgets/DisassemblerMetadataDialog.h \
|
||||
src/binaryfile/EntryPointModel.h \
|
||||
src/ui/widgets/LocationInfoDialog.h \
|
||||
src/binaryfile/EntryPoints.h \
|
||||
src/binaryfile/AssemblerSymbols.h \
|
||||
src/binaryfile/AssemblerSymbolModel.h \
|
||||
src/binaryfile/MemoryUsageMap.h \
|
||||
src/ui/diskexplorer/DiskExplorer.h \
|
||||
src/ui/diskexplorer/DiskExplorerMapWidget.h \
|
||||
src/applesoftfile/ApplesoftRetokenizer.h \
|
||||
src/util/AppleColors.h \
|
||||
src/internals/JumpLineManager.h \
|
||||
src/ui/widgets/FlowLineTextBrowser.h \
|
||||
src/ui/widgets/asciiinfodialog.h
|
||||
|
||||
FORMS += \
|
||||
src/ui/catalogwidget.ui \
|
||||
src/ui/viewers/applesoftfileviewer.ui \
|
||||
src/ui/viewers/disassemblerviewer.ui \
|
||||
src/ui/viewers/hexdumpviewer.ui \
|
||||
src/ui/viewers/intbasicfileviewer.ui \
|
||||
src/ui/viewers/texthexdumpviewer.ui \
|
||||
src/ui/viewers/applesoftfiledetailviewer.ui \
|
||||
src/ui/widgets/hexconverter.ui \
|
||||
src/ui/widgets/hrcgcontrolsinfo.ui \
|
||||
src/ui/viewers/viewerbase.ui \
|
||||
src/ui/widgets/CharacterSetExplorer.ui \
|
||||
src/ui/widgets/DisassemblerMetadataDialog.ui \
|
||||
src/ui/widgets/LocationInfoDialog.ui \
|
||||
src/ui/widgets/asciiinfodialog.ui
|
||||
|
44
LICENSE
44
LICENSE
@ -1,22 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Mark D. Long
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Mark D. Long
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
84
README.md
84
README.md
@ -1,42 +1,42 @@
|
||||
# AppleSAWS
|
||||
##Apple Software Analysis WorkShop
|
||||
|
||||
This is a toolkit for exploring DOS 3.3 disk contents. I started this because I had become interested in a game that I used to play a long time ago and I wanted to dig deeper into the internals of how it worked. Since it was a nice combination of a series of Applesoft and Binary files, I decided that a tool to help explore those types of things would be handy. Of course, I've ended up spending far more time writing the tool than I have actually exploring the game, but nonetheless, it's been a fun ongoing project.
|
||||
|
||||
This code is being developed using Qt5, with development work being done on Linux, but it should compile and run without problems on Windows and Mac.
|
||||
|
||||
Among other things, the app includes:
|
||||
* Code that reads and parses DOS-format disk images at the disk-structure level. (It's just read-only for now, and ProDOS is on the horizon)
|
||||
* An Applesoft parser/retokenizer/reformatter which can show code in its normal form or reindented on multiple lines with syntax highlighting, and can optionally show integers as hex values inline. The retokenizer creates new tokens for strings, variable names, numeric values, DATA payloads, REM remarks, and other things that are nice to have -- and sets the stage to create an analyzer for deeper processing of the code later on.
|
||||
* A binary file processor with a flow-tracing disassembler, which can show hex dumps and disassembly of code and data blocks (it also temporarily has some common labels for well-known addresses hard-coded into the display, though dynamic labeling of symbols is in the works.) It can also display the relocation table for type-R relocatable files. It also displays a linear graph of jumps, subroutines, and branches!
|
||||
* A Text file viewer.
|
||||
* A graphics viewer which can show hires screen dumps as monochrome, with NTSC artifacts, or a hybrid mode where each pixel's natural color is shown in-place (with no white color blending.)
|
||||
* An HRCG character set viewer and explorer
|
||||
* Exporting files and graphics to the local filesystem (as either .txt or .png files, as appropriate)
|
||||
* A disk explorer which allows viewing the disk at the sector level, exploring directory and VTOC structure, and more!
|
||||
* (Though not useful to most) A maze viewer for the game which I was originally exploring (Datamost's *The Missing Ring*, by Terry Romine, 1982)
|
||||
* Probably some other stuff I can't think of at the moment.
|
||||
|
||||
There is also a Hex/Decimal converter utility and some in-app documentation for HRCG control character codes. Mainly stuff that I found useful at the time I was writing it.
|
||||
|
||||
In the pipeline are some more useful features (as I get a chance):
|
||||
* Syntax Highlighting **(Currently in progress!)**
|
||||
* More low-level disk exploration tools (sector-level stuff, comparing DOS versions between disks, etc.)
|
||||
* More analysis of Applesoft programs (Tracing flow control; determining unaccessable lines of code; finding addresses of PEEKS, POKES, CALLS, USRs, and &'s; determining "hidden" areas of memory stuffed between lines or after the end of the program itself)
|
||||
* Processing and analysis of Integer Basic files
|
||||
* Much more robust disassembly tools:
|
||||
* Handling differences between 6502/65C02/65816 ops, as well as "undocumented" ops on the original 6502
|
||||
* Automated detection of Code Segments vs Data Segments **(Currently in progress!)**
|
||||
* Allowing user-defined labels for addresses **(Currently in progress!)**
|
||||
* Shape table processing and viewing
|
||||
* ProDOS support
|
||||
* Modification/Writing disk images
|
||||
* Lots of optimization and refactoring -- **(Ongoing)**
|
||||
* Tools for processing DHGR graphics
|
||||
* Introduction of project management, allowing annotation and documention of interconnectivity between files and disk image contents, as well as preferences of groups of default viewers to open for a given image or set of images **(In progress!)**
|
||||
* Plenty of other stuff!
|
||||
|
||||
Anyway, if you take a look at it and think it's interesting, I'd love to hear some feedback.
|
||||
|
||||

|
||||
|
||||
# AppleSAWS
|
||||
##Apple Software Analysis WorkShop
|
||||
|
||||
This is a toolkit for exploring DOS 3.3 disk contents. I started this because I had become interested in a game that I used to play a long time ago and I wanted to dig deeper into the internals of how it worked. Since it was a nice combination of a series of Applesoft and Binary files, I decided that a tool to help explore those types of things would be handy. Of course, I've ended up spending far more time writing the tool than I have actually exploring the game, but nonetheless, it's been a fun ongoing project.
|
||||
|
||||
This code is being developed using Qt5, with development work being done on Linux, but it should compile and run without problems on Windows and Mac.
|
||||
|
||||
Among other things, the app includes:
|
||||
* Code that reads and parses DOS-format disk images at the disk-structure level. (It's just read-only for now, and ProDOS is on the horizon)
|
||||
* An Applesoft parser/retokenizer/reformatter which can show code in its normal form or reindented on multiple lines with syntax highlighting, and can optionally show integers as hex values inline. The retokenizer creates new tokens for strings, variable names, numeric values, DATA payloads, REM remarks, and other things that are nice to have -- and sets the stage to create an analyzer for deeper processing of the code later on.
|
||||
* A binary file processor with a flow-tracing disassembler, which can show hex dumps and disassembly of code and data blocks (it also temporarily has some common labels for well-known addresses hard-coded into the display, though dynamic labeling of symbols is in the works.) It can also display the relocation table for type-R relocatable files. It also displays a linear graph of jumps, subroutines, and branches!
|
||||
* A Text file viewer.
|
||||
* A graphics viewer which can show hires screen dumps as monochrome, with NTSC artifacts, or a hybrid mode where each pixel's natural color is shown in-place (with no white color blending.)
|
||||
* An HRCG character set viewer and explorer
|
||||
* Exporting files and graphics to the local filesystem (as either .txt or .png files, as appropriate)
|
||||
* A disk explorer which allows viewing the disk at the sector level, exploring directory and VTOC structure, and more!
|
||||
* (Though not useful to most) A maze viewer for the game which I was originally exploring (Datamost's *The Missing Ring*, by Terry Romine, 1982)
|
||||
* Probably some other stuff I can't think of at the moment.
|
||||
|
||||
There is also a Hex/Decimal converter utility and some in-app documentation for HRCG control character codes. Mainly stuff that I found useful at the time I was writing it.
|
||||
|
||||
In the pipeline are some more useful features (as I get a chance):
|
||||
* Syntax Highlighting **(Currently in progress!)**
|
||||
* More low-level disk exploration tools (sector-level stuff, comparing DOS versions between disks, etc.)
|
||||
* More analysis of Applesoft programs (Tracing flow control; determining unaccessable lines of code; finding addresses of PEEKS, POKES, CALLS, USRs, and &'s; determining "hidden" areas of memory stuffed between lines or after the end of the program itself)
|
||||
* Processing and analysis of Integer Basic files
|
||||
* Much more robust disassembly tools:
|
||||
* Handling differences between 6502/65C02/65816 ops, as well as "undocumented" ops on the original 6502
|
||||
* Automated detection of Code Segments vs Data Segments **(Currently in progress!)**
|
||||
* Allowing user-defined labels for addresses **(Currently in progress!)**
|
||||
* Shape table processing and viewing
|
||||
* ProDOS support
|
||||
* Modification/Writing disk images
|
||||
* Lots of optimization and refactoring -- **(Ongoing)**
|
||||
* Tools for processing DHGR graphics
|
||||
* Introduction of project management, allowing annotation and documention of interconnectivity between files and disk image contents, as well as preferences of groups of default viewers to open for a given image or set of images **(In progress!)**
|
||||
* Plenty of other stuff!
|
||||
|
||||
Anyway, if you take a look at it and think it's interesting, I'd love to hear some feedback.
|
||||
|
||||

|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,52 +1,52 @@
|
||||
#ifndef APPLESOFTRETOKENIZER_H
|
||||
#define APPLESOFTRETOKENIZER_H
|
||||
|
||||
#include "applesoftline.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
|
||||
class ApplesoftRetokenizer
|
||||
{
|
||||
public:
|
||||
ApplesoftRetokenizer();
|
||||
|
||||
void setData(QByteArray data);
|
||||
void parse(quint16 start_address = 0x0801);
|
||||
|
||||
quint16 getEndOfDataOffset() const { return m_data_end; }
|
||||
|
||||
QVector<ApplesoftLine> getRetokenizedLines() { return m_retokenized_lines; }
|
||||
|
||||
QList<QPair<quint16, quint16> > getFlowTargets() const { return m_flowTargets; }
|
||||
|
||||
private:
|
||||
void retokenizeLinesForFormatting();
|
||||
|
||||
|
||||
void retokenizeLine(ApplesoftLine &line);
|
||||
QList<ApplesoftToken> retokenizeRems(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeStrings(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeDataStatements(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeDataPayload(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeVariables(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeNumbers(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeNegativeNumbers(QList<ApplesoftToken> &datatokens);
|
||||
|
||||
|
||||
QVector<ApplesoftLine> m_retokenized_lines;
|
||||
QByteArray m_data;
|
||||
|
||||
quint16 m_data_end;
|
||||
|
||||
bool m_isParsed;
|
||||
|
||||
QList<QPair<quint16, quint16> > m_flowTargets;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // APPLESOFTRETOKENIZER_H
|
||||
|
||||
#ifndef APPLESOFTRETOKENIZER_H
|
||||
#define APPLESOFTRETOKENIZER_H
|
||||
|
||||
#include "applesoftline.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
|
||||
class ApplesoftRetokenizer
|
||||
{
|
||||
public:
|
||||
ApplesoftRetokenizer();
|
||||
|
||||
void setData(QByteArray data);
|
||||
void parse(quint16 start_address = 0x0801);
|
||||
|
||||
quint16 getEndOfDataOffset() const { return m_data_end; }
|
||||
|
||||
QVector<ApplesoftLine> getRetokenizedLines() { return m_retokenized_lines; }
|
||||
|
||||
QList<QPair<quint16, quint16> > getFlowTargets() const { return m_flowTargets; }
|
||||
|
||||
private:
|
||||
void retokenizeLinesForFormatting();
|
||||
|
||||
|
||||
void retokenizeLine(ApplesoftLine &line);
|
||||
QList<ApplesoftToken> retokenizeRems(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeStrings(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeDataStatements(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeDataPayload(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeVariables(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeNumbers(QList<ApplesoftToken> &datatokens);
|
||||
QList<ApplesoftToken> retokenizeNegativeNumbers(QList<ApplesoftToken> &datatokens);
|
||||
|
||||
|
||||
QVector<ApplesoftLine> m_retokenized_lines;
|
||||
QByteArray m_data;
|
||||
|
||||
quint16 m_data_end;
|
||||
|
||||
bool m_isParsed;
|
||||
|
||||
QList<QPair<quint16, quint16> > m_flowTargets;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // APPLESOFTRETOKENIZER_H
|
||||
|
||||
|
@ -1,78 +1,78 @@
|
||||
#include "applesoftfile.h"
|
||||
#include "util.h"
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
#include <QRegularExpressionMatchIterator>
|
||||
#include <QList>
|
||||
|
||||
ApplesoftFile::ApplesoftFile(QByteArray data) : GenericFile(data)
|
||||
{
|
||||
m_retokenizer = Q_NULLPTR;
|
||||
m_data_end = data.length();
|
||||
|
||||
if (!data.isEmpty())
|
||||
{
|
||||
setData(data);
|
||||
}
|
||||
setAddress(0x801);
|
||||
}
|
||||
|
||||
void ApplesoftFile::setData(QByteArray data)
|
||||
{
|
||||
if (!m_retokenizer)
|
||||
{
|
||||
m_retokenizer = new ApplesoftRetokenizer();
|
||||
}
|
||||
|
||||
GenericFile::setData(data);
|
||||
|
||||
quint8 addlo = m_data.at(0);
|
||||
quint8 addhi = m_data.at(1);
|
||||
m_length = makeWord(addlo,addhi);
|
||||
m_data.remove(0,2);
|
||||
|
||||
m_retokenizer->setData(m_data);
|
||||
m_retokenizer->parse();
|
||||
m_data_end = m_retokenizer->getEndOfDataOffset();
|
||||
m_lines = m_retokenizer->getRetokenizedLines();
|
||||
|
||||
m_flowTargets = m_retokenizer->getFlowTargets();
|
||||
}
|
||||
|
||||
QByteArray ApplesoftFile::rawData() {
|
||||
QByteArray retval;
|
||||
retval.append(m_length % 255);
|
||||
retval.append(m_length / 255);
|
||||
retval.append(m_data);
|
||||
return retval;
|
||||
}
|
||||
|
||||
QStringList ApplesoftFile::extraDataHexValues() {
|
||||
QStringList retval;
|
||||
|
||||
QString debugline = "";
|
||||
int count = 0;
|
||||
foreach (quint8 val, extraData()) {
|
||||
debugline.append(QString("%1").arg(val,2,16,QChar('0')).toUpper());
|
||||
count++;
|
||||
if (count == 16) {
|
||||
retval.append(debugline);
|
||||
debugline = "";
|
||||
count = 0;
|
||||
} else {
|
||||
debugline.append(" ");
|
||||
}
|
||||
}
|
||||
if (!debugline.simplified().isEmpty()) {
|
||||
retval.append(debugline);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
QByteArray ApplesoftFile::extraData()
|
||||
{
|
||||
return m_data.mid(m_data_end);
|
||||
}
|
||||
|
||||
|
||||
#include "applesoftfile.h"
|
||||
#include "util.h"
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
#include <QRegularExpressionMatchIterator>
|
||||
#include <QList>
|
||||
|
||||
ApplesoftFile::ApplesoftFile(QByteArray data) : GenericFile(data)
|
||||
{
|
||||
m_retokenizer = Q_NULLPTR;
|
||||
m_data_end = data.length();
|
||||
|
||||
if (!data.isEmpty())
|
||||
{
|
||||
setData(data);
|
||||
}
|
||||
setAddress(0x801);
|
||||
}
|
||||
|
||||
void ApplesoftFile::setData(QByteArray data)
|
||||
{
|
||||
if (!m_retokenizer)
|
||||
{
|
||||
m_retokenizer = new ApplesoftRetokenizer();
|
||||
}
|
||||
|
||||
GenericFile::setData(data);
|
||||
|
||||
quint8 addlo = m_data.at(0);
|
||||
quint8 addhi = m_data.at(1);
|
||||
m_length = makeWord(addlo,addhi);
|
||||
m_data.remove(0,2);
|
||||
|
||||
m_retokenizer->setData(m_data);
|
||||
m_retokenizer->parse();
|
||||
m_data_end = m_retokenizer->getEndOfDataOffset();
|
||||
m_lines = m_retokenizer->getRetokenizedLines();
|
||||
|
||||
m_flowTargets = m_retokenizer->getFlowTargets();
|
||||
}
|
||||
|
||||
QByteArray ApplesoftFile::rawData() {
|
||||
QByteArray retval;
|
||||
retval.append(m_length % 255);
|
||||
retval.append(m_length / 255);
|
||||
retval.append(m_data);
|
||||
return retval;
|
||||
}
|
||||
|
||||
QStringList ApplesoftFile::extraDataHexValues() {
|
||||
QStringList retval;
|
||||
|
||||
QString debugline = "";
|
||||
int count = 0;
|
||||
foreach (quint8 val, extraData()) {
|
||||
debugline.append(QString("%1").arg(val,2,16,QChar('0')).toUpper());
|
||||
count++;
|
||||
if (count == 16) {
|
||||
retval.append(debugline);
|
||||
debugline = "";
|
||||
count = 0;
|
||||
} else {
|
||||
debugline.append(" ");
|
||||
}
|
||||
}
|
||||
if (!debugline.simplified().isEmpty()) {
|
||||
retval.append(debugline);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
QByteArray ApplesoftFile::extraData()
|
||||
{
|
||||
return m_data.mid(m_data_end);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,43 +1,43 @@
|
||||
#ifndef APPLESOFTFILE_H
|
||||
#define APPLESOFTFILE_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
|
||||
#include "applesoftline.h"
|
||||
#include "genericfile.h"
|
||||
#include "applesofttoken.h"
|
||||
#include "ApplesoftRetokenizer.h"
|
||||
|
||||
|
||||
class ApplesoftFile : public GenericFile
|
||||
{
|
||||
public:
|
||||
ApplesoftFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
QByteArray extraData();
|
||||
QStringList extraDataHexValues();
|
||||
|
||||
QVector<ApplesoftLine> getLines() const { return m_lines; }
|
||||
|
||||
quint16 length() const { return m_length; }
|
||||
|
||||
QByteArray rawData();
|
||||
|
||||
private:
|
||||
|
||||
QVector<ApplesoftLine> m_lines;
|
||||
int m_data_end;
|
||||
quint16 m_length;
|
||||
|
||||
ApplesoftRetokenizer *m_retokenizer;
|
||||
|
||||
QList<QPair<quint16, quint16> > m_flowTargets;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // APPLESOFTFILE_H
|
||||
#ifndef APPLESOFTFILE_H
|
||||
#define APPLESOFTFILE_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
|
||||
#include "applesoftline.h"
|
||||
#include "genericfile.h"
|
||||
#include "applesofttoken.h"
|
||||
#include "ApplesoftRetokenizer.h"
|
||||
|
||||
|
||||
class ApplesoftFile : public GenericFile
|
||||
{
|
||||
public:
|
||||
ApplesoftFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
QByteArray extraData();
|
||||
QStringList extraDataHexValues();
|
||||
|
||||
QVector<ApplesoftLine> getLines() const { return m_lines; }
|
||||
|
||||
quint16 length() const { return m_length; }
|
||||
|
||||
QByteArray rawData();
|
||||
|
||||
private:
|
||||
|
||||
QVector<ApplesoftLine> m_lines;
|
||||
int m_data_end;
|
||||
quint16 m_length;
|
||||
|
||||
ApplesoftRetokenizer *m_retokenizer;
|
||||
|
||||
QList<QPair<quint16, quint16> > m_flowTargets;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // APPLESOFTFILE_H
|
||||
|
@ -1,174 +1,174 @@
|
||||
#include "applesoftformatter.h"
|
||||
#include "util.h"
|
||||
#include <QTextCursor>
|
||||
#include <QTextCharFormat>
|
||||
#include <QChar>
|
||||
|
||||
#define HEXPREFIX "0x"
|
||||
|
||||
ApplesoftFormatter::ApplesoftFormatter(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_file = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void ApplesoftFormatter::setFile(ApplesoftFile *file)
|
||||
{
|
||||
m_file = file;
|
||||
emit newFile(file);
|
||||
}
|
||||
|
||||
void ApplesoftFormatter::formatDocument(QTextDocument *doc)
|
||||
{
|
||||
if (!doc) return;
|
||||
|
||||
doc->clear();
|
||||
QTextCursor cursor(doc);
|
||||
cursor.beginEditBlock();
|
||||
|
||||
bool synhl = (m_format_options.testFlag(SyntaxHighlighting));
|
||||
|
||||
foreach (ApplesoftLine line, m_file->getLines())
|
||||
{
|
||||
QString linestring = QString("%1 ").arg(line.linenum,5,10,QChar(' '));
|
||||
|
||||
if (synhl)
|
||||
{
|
||||
cursor.insertText(linestring,
|
||||
ApplesoftToken::textFormat(ApplesoftToken::LineNumberTokenVal));
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor.insertText(linestring,ApplesoftToken::defaultTextFormat());
|
||||
}
|
||||
|
||||
QVectorIterator<ApplesoftToken>tokenIt(line.tokens);
|
||||
bool isBranchTarget = false;
|
||||
while (tokenIt.hasNext())
|
||||
{
|
||||
ApplesoftToken token = tokenIt.next();
|
||||
if (token.isOptFmtToken())
|
||||
{
|
||||
switch (token.getTokenId())
|
||||
{
|
||||
|
||||
case ApplesoftToken::OptFmtFlagFlowTargetNextTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ShowIntsAsHex))
|
||||
isBranchTarget = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ApplesoftToken::OptFmtIndentLineBreakTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ReindentCode))
|
||||
cursor.insertBlock();
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtIndentSpaceTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ReindentCode))
|
||||
cursor.insertText(" ",ApplesoftToken::defaultTextFormat());
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtIndentTabTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ReindentCode))
|
||||
cursor.insertText(" ",ApplesoftToken::defaultTextFormat());
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtLeadingSpaceTokenValue:
|
||||
{
|
||||
cursor.insertText(" ",ApplesoftToken::defaultTextFormat());
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtReturnLineBreakTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(BreakAfterReturn))
|
||||
cursor.insertBlock();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // isOptFmt
|
||||
else
|
||||
{
|
||||
QString tokenstr = token.getRawPrintableString();
|
||||
|
||||
|
||||
QTextCharFormat fmt = ApplesoftToken::defaultTextFormat();
|
||||
if (synhl) fmt = token.textFormat();
|
||||
|
||||
|
||||
if (token.getTokenId() == ApplesoftToken::IntegerTokenVal)
|
||||
{
|
||||
if (m_format_options.testFlag(ShowIntsAsHex) && !isBranchTarget)
|
||||
{
|
||||
quint32 ui32val = token.getUnsignedIntegerValue();
|
||||
qint32 i32val = token.getIntegerValue();
|
||||
if ((i32val < 128 && i32val >= -128) || ui32val < 256)
|
||||
{
|
||||
quint8 ui8 = ui32val;
|
||||
tokenstr = HEXPREFIX+uint8ToHex(ui8);
|
||||
}
|
||||
else if ((i32val < 32768 && i32val >= -32768) || ui32val < 65536)
|
||||
{
|
||||
quint16 ui16 = ui32val;
|
||||
tokenstr = HEXPREFIX+uint16ToHex(ui16);
|
||||
}
|
||||
else
|
||||
{
|
||||
tokenstr = HEXPREFIX+uint32ToHex(ui32val);
|
||||
}
|
||||
} // isShowIntsAsHex
|
||||
isBranchTarget = false;
|
||||
}
|
||||
|
||||
// if (m_format_options.testFlag(ShowCtrlChars))
|
||||
// {
|
||||
// tokenstr.replace(QChar(0x7f),QChar(0x2401));
|
||||
|
||||
// for (int idx = 1; idx <= 0x1f; idx++) {
|
||||
// if (idx == '\n') continue;
|
||||
// tokenstr.replace(QChar(idx),QChar(idx+0x2400));
|
||||
// }
|
||||
// } // if ShowCtrlChars
|
||||
|
||||
|
||||
|
||||
QTextCharFormat invFormat = ApplesoftToken::defaultInverseTextFormat();
|
||||
if (m_format_options.testFlag(SyntaxHighlighting))
|
||||
invFormat = ApplesoftToken::textFormat(
|
||||
ApplesoftToken::ControlCharTokenVal);
|
||||
|
||||
|
||||
foreach (QChar ch, tokenstr)
|
||||
{
|
||||
if (ch == QChar(0x7f))
|
||||
{
|
||||
cursor.insertText(QChar(0x00d7),invFormat);
|
||||
}
|
||||
else if (ch < QChar(' '))
|
||||
{
|
||||
if (m_format_options.testFlag(ShowCtrlChars))
|
||||
{
|
||||
QChar newch = ch.unicode()+0x40;
|
||||
cursor.insertText(newch,invFormat);
|
||||
}
|
||||
}
|
||||
else cursor.insertText(ch,fmt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // while tokenIt.hasNext()
|
||||
|
||||
//formattedText.append("\n");
|
||||
cursor.insertBlock();
|
||||
|
||||
} // foreach line
|
||||
cursor.endEditBlock();
|
||||
}
|
||||
#include "applesoftformatter.h"
|
||||
#include "util.h"
|
||||
#include <QTextCursor>
|
||||
#include <QTextCharFormat>
|
||||
#include <QChar>
|
||||
|
||||
#define HEXPREFIX "0x"
|
||||
|
||||
ApplesoftFormatter::ApplesoftFormatter(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_file = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void ApplesoftFormatter::setFile(ApplesoftFile *file)
|
||||
{
|
||||
m_file = file;
|
||||
emit newFile(file);
|
||||
}
|
||||
|
||||
void ApplesoftFormatter::formatDocument(QTextDocument *doc)
|
||||
{
|
||||
if (!doc) return;
|
||||
|
||||
doc->clear();
|
||||
QTextCursor cursor(doc);
|
||||
cursor.beginEditBlock();
|
||||
|
||||
bool synhl = (m_format_options.testFlag(SyntaxHighlighting));
|
||||
|
||||
foreach (ApplesoftLine line, m_file->getLines())
|
||||
{
|
||||
QString linestring = QString("%1 ").arg(line.linenum,5,10,QChar(' '));
|
||||
|
||||
if (synhl)
|
||||
{
|
||||
cursor.insertText(linestring,
|
||||
ApplesoftToken::textFormat(ApplesoftToken::LineNumberTokenVal));
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor.insertText(linestring,ApplesoftToken::defaultTextFormat());
|
||||
}
|
||||
|
||||
QVectorIterator<ApplesoftToken>tokenIt(line.tokens);
|
||||
bool isBranchTarget = false;
|
||||
while (tokenIt.hasNext())
|
||||
{
|
||||
ApplesoftToken token = tokenIt.next();
|
||||
if (token.isOptFmtToken())
|
||||
{
|
||||
switch (token.getTokenId())
|
||||
{
|
||||
|
||||
case ApplesoftToken::OptFmtFlagFlowTargetNextTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ShowIntsAsHex))
|
||||
isBranchTarget = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ApplesoftToken::OptFmtIndentLineBreakTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ReindentCode))
|
||||
cursor.insertBlock();
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtIndentSpaceTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ReindentCode))
|
||||
cursor.insertText(" ",ApplesoftToken::defaultTextFormat());
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtIndentTabTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(ReindentCode))
|
||||
cursor.insertText(" ",ApplesoftToken::defaultTextFormat());
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtLeadingSpaceTokenValue:
|
||||
{
|
||||
cursor.insertText(" ",ApplesoftToken::defaultTextFormat());
|
||||
break;
|
||||
}
|
||||
case ApplesoftToken::OptFmtReturnLineBreakTokenValue:
|
||||
{
|
||||
if (m_format_options.testFlag(BreakAfterReturn))
|
||||
cursor.insertBlock();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // isOptFmt
|
||||
else
|
||||
{
|
||||
QString tokenstr = token.getRawPrintableString();
|
||||
|
||||
|
||||
QTextCharFormat fmt = ApplesoftToken::defaultTextFormat();
|
||||
if (synhl) fmt = token.textFormat();
|
||||
|
||||
|
||||
if (token.getTokenId() == ApplesoftToken::IntegerTokenVal)
|
||||
{
|
||||
if (m_format_options.testFlag(ShowIntsAsHex) && !isBranchTarget)
|
||||
{
|
||||
quint32 ui32val = token.getUnsignedIntegerValue();
|
||||
qint32 i32val = token.getIntegerValue();
|
||||
if ((i32val < 128 && i32val >= -128) || ui32val < 256)
|
||||
{
|
||||
quint8 ui8 = ui32val;
|
||||
tokenstr = HEXPREFIX+uint8ToHex(ui8);
|
||||
}
|
||||
else if ((i32val < 32768 && i32val >= -32768) || ui32val < 65536)
|
||||
{
|
||||
quint16 ui16 = ui32val;
|
||||
tokenstr = HEXPREFIX+uint16ToHex(ui16);
|
||||
}
|
||||
else
|
||||
{
|
||||
tokenstr = HEXPREFIX+uint32ToHex(ui32val);
|
||||
}
|
||||
} // isShowIntsAsHex
|
||||
isBranchTarget = false;
|
||||
}
|
||||
|
||||
// if (m_format_options.testFlag(ShowCtrlChars))
|
||||
// {
|
||||
// tokenstr.replace(QChar(0x7f),QChar(0x2401));
|
||||
|
||||
// for (int idx = 1; idx <= 0x1f; idx++) {
|
||||
// if (idx == '\n') continue;
|
||||
// tokenstr.replace(QChar(idx),QChar(idx+0x2400));
|
||||
// }
|
||||
// } // if ShowCtrlChars
|
||||
|
||||
|
||||
|
||||
QTextCharFormat invFormat = ApplesoftToken::defaultInverseTextFormat();
|
||||
if (m_format_options.testFlag(SyntaxHighlighting))
|
||||
invFormat = ApplesoftToken::textFormat(
|
||||
ApplesoftToken::ControlCharTokenVal);
|
||||
|
||||
|
||||
foreach (QChar ch, tokenstr)
|
||||
{
|
||||
if (ch == QChar(0x7f))
|
||||
{
|
||||
cursor.insertText(QChar(0x00d7),invFormat);
|
||||
}
|
||||
else if (ch < QChar(' '))
|
||||
{
|
||||
if (m_format_options.testFlag(ShowCtrlChars))
|
||||
{
|
||||
QChar newch = ch.unicode()+0x40;
|
||||
cursor.insertText(newch,invFormat);
|
||||
}
|
||||
}
|
||||
else cursor.insertText(ch,fmt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // while tokenIt.hasNext()
|
||||
|
||||
//formattedText.append("\n");
|
||||
cursor.insertBlock();
|
||||
|
||||
} // foreach line
|
||||
cursor.endEditBlock();
|
||||
}
|
||||
|
@ -1,53 +1,53 @@
|
||||
#ifndef APPLESOFTFORMATTER_H
|
||||
#define APPLESOFTFORMATTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QFlags>
|
||||
#include <QTextDocument>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "applesoftfile.h"
|
||||
|
||||
class ApplesoftFormatter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum FormatOption {
|
||||
NoOptions = 0x00,
|
||||
|
||||
SyntaxHighlighting = 0x01,
|
||||
ShowCtrlChars = 0x02,
|
||||
BreakAfterReturn = 0x04,
|
||||
ReindentCode = 0x08,
|
||||
ShowIntsAsHex = 0x10,
|
||||
|
||||
AllFlags = 0xffffffff
|
||||
};
|
||||
Q_DECLARE_FLAGS(FormatOptions, FormatOption)
|
||||
|
||||
public:
|
||||
explicit ApplesoftFormatter(QObject *parent = 0);
|
||||
void setFlags(FormatOptions options) { m_format_options = options; }
|
||||
void setFile(ApplesoftFile *file);
|
||||
|
||||
FormatOptions flags() { return m_format_options; }
|
||||
|
||||
void formatDocument(QTextDocument *doc);
|
||||
|
||||
signals:
|
||||
void newFile(ApplesoftFile *file);
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
FormatOptions m_format_options;
|
||||
|
||||
ApplesoftFile *m_file;
|
||||
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(ApplesoftFormatter::FormatOptions)
|
||||
|
||||
#endif // APPLESOFTFORMATTER_H
|
||||
#ifndef APPLESOFTFORMATTER_H
|
||||
#define APPLESOFTFORMATTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QFlags>
|
||||
#include <QTextDocument>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "applesoftfile.h"
|
||||
|
||||
class ApplesoftFormatter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum FormatOption {
|
||||
NoOptions = 0x00,
|
||||
|
||||
SyntaxHighlighting = 0x01,
|
||||
ShowCtrlChars = 0x02,
|
||||
BreakAfterReturn = 0x04,
|
||||
ReindentCode = 0x08,
|
||||
ShowIntsAsHex = 0x10,
|
||||
|
||||
AllFlags = 0xffffffff
|
||||
};
|
||||
Q_DECLARE_FLAGS(FormatOptions, FormatOption)
|
||||
|
||||
public:
|
||||
explicit ApplesoftFormatter(QObject *parent = 0);
|
||||
void setFlags(FormatOptions options) { m_format_options = options; }
|
||||
void setFile(ApplesoftFile *file);
|
||||
|
||||
FormatOptions flags() { return m_format_options; }
|
||||
|
||||
void formatDocument(QTextDocument *doc);
|
||||
|
||||
signals:
|
||||
void newFile(ApplesoftFile *file);
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
FormatOptions m_format_options;
|
||||
|
||||
ApplesoftFile *m_file;
|
||||
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(ApplesoftFormatter::FormatOptions)
|
||||
|
||||
#endif // APPLESOFTFORMATTER_H
|
||||
|
@ -1,16 +1,16 @@
|
||||
#ifndef APPLESOFTLINE_H
|
||||
#define APPLESOFTLINE_H
|
||||
#include <Qt>
|
||||
#include <QVector>
|
||||
|
||||
class ApplesoftToken;
|
||||
|
||||
struct ApplesoftLine {
|
||||
qint16 address;
|
||||
quint16 next_address;
|
||||
quint16 linenum;
|
||||
QVector<ApplesoftToken> tokens;
|
||||
};
|
||||
|
||||
|
||||
#endif // APPLESOFTLINE_H
|
||||
#ifndef APPLESOFTLINE_H
|
||||
#define APPLESOFTLINE_H
|
||||
#include <Qt>
|
||||
#include <QVector>
|
||||
|
||||
class ApplesoftToken;
|
||||
|
||||
struct ApplesoftLine {
|
||||
qint16 address;
|
||||
quint16 next_address;
|
||||
quint16 linenum;
|
||||
QVector<ApplesoftToken> tokens;
|
||||
};
|
||||
|
||||
|
||||
#endif // APPLESOFTLINE_H
|
||||
|
@ -1,360 +1,360 @@
|
||||
#include "applesofttoken.h"
|
||||
|
||||
QMap<quint16, QString> ApplesoftToken::m_tokens = QMap<quint16, QString>();
|
||||
|
||||
ApplesoftToken::ApplesoftToken()
|
||||
{
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
setTokenId(DefaultTokenVal);
|
||||
}
|
||||
|
||||
ApplesoftToken::ApplesoftToken(quint16 id)
|
||||
{
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
setTokenId(id);
|
||||
}
|
||||
|
||||
ApplesoftToken::ApplesoftToken(quint16 id, QVariant payload)
|
||||
{
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
setTokenId(id);
|
||||
setValue(payload);
|
||||
}
|
||||
|
||||
void ApplesoftToken::setTokenId(quint16 id)
|
||||
{
|
||||
m_token_id = id;
|
||||
m_token_type = UNKNOWN_TOKEN;
|
||||
m_command_type = NONE;
|
||||
|
||||
if (id <= 0x7f) {
|
||||
setValue(id);
|
||||
m_token_type = ASCIICHAR_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id <= 0xC7) {
|
||||
setValue(id);
|
||||
m_token_type = APPLESOFT_TOKEN;
|
||||
m_command_type = COMMAND;
|
||||
} else if (id <= 0xD1) {
|
||||
setValue(id);
|
||||
m_token_type = APPLESOFT_TOKEN;
|
||||
m_command_type = OPERATOR;
|
||||
} else if (id <= 0xEA) {
|
||||
setValue(id);
|
||||
m_token_type = APPLESOFT_TOKEN;
|
||||
m_command_type = FUNCTION;
|
||||
} else if (id <= 0xFF) {
|
||||
setValue(id);
|
||||
m_token_type = UNDEFINED_APPLESOFT_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == StringTokenVal) {
|
||||
m_token_type = STRING_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == RemStringTokenVal) {
|
||||
m_token_type = REM_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == DataStringTokenVal) {
|
||||
m_token_type = DATASTRING_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == IntegerTokenVal) {
|
||||
m_token_type = INTEGER_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == FloatTokenVal) {
|
||||
m_token_type = FLOAT_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == IntVarTokenVal) {
|
||||
m_token_type = INT_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == IntAryVarTokenVal) {
|
||||
m_token_type = INT_ARY_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == FloatVarTokenVal) {
|
||||
m_token_type = FLOAT_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == FloatAryVarTokenVal) {
|
||||
m_token_type = FLOAT_ARY_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == StringVarTokenVal) {
|
||||
m_token_type = STRING_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == StringAryVarTokenVal) {
|
||||
m_token_type = STRING_ARY_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id >= 0xe000 && id < 0xf000) {
|
||||
m_token_type = OPTIONAL_FORMAT_TOKEN;
|
||||
m_command_type = OPTIONAL_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplesoftToken::setValue(QVariant value)
|
||||
{
|
||||
m_payload = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString ApplesoftToken::getRawPrintableString() const
|
||||
{
|
||||
if (m_token_id == DefaultTokenVal) {
|
||||
return "";
|
||||
} else if (m_token_id == 0x00) {
|
||||
return "";
|
||||
} else if (m_token_id <= 0x7f) {
|
||||
return QString((m_token_id));
|
||||
} else if (m_token_id <= 0xff) {
|
||||
return m_tokens[m_token_id];
|
||||
} else if (m_token_id == StringTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == RemStringTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == DataStringTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == IntegerTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == FloatTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == IntVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == IntAryVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == FloatVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == FloatAryVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == StringVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == StringAryVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id >= 0xe000 && m_token_id < 0xf000) {
|
||||
return "";
|
||||
} else {
|
||||
return "[temp undefined]";
|
||||
}
|
||||
}
|
||||
|
||||
QTextCharFormat ApplesoftToken::defaultTextFormat()
|
||||
{
|
||||
QTextCharFormat tf; // Default
|
||||
tf.setForeground(Qt::black);
|
||||
return tf;
|
||||
}
|
||||
|
||||
QTextCharFormat ApplesoftToken::defaultInverseTextFormat()
|
||||
{
|
||||
QTextCharFormat tf;
|
||||
tf.setForeground(Qt::white);
|
||||
tf.setBackground(Qt::black);
|
||||
return tf;
|
||||
}
|
||||
|
||||
QTextCharFormat ApplesoftToken::textFormat(quint16 tokenType)
|
||||
{
|
||||
QTextCharFormat tf = defaultTextFormat();
|
||||
|
||||
if (tokenType < 0x80) // Ascii
|
||||
{
|
||||
tf.setForeground(Qt::black);
|
||||
}
|
||||
else if (tokenType < 0x100) // Applesoft Tokens
|
||||
{
|
||||
tf.setForeground(Qt::black);
|
||||
}
|
||||
else if (tokenType == StringTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::blue);
|
||||
tf.setFontWeight(QFont::Bold);
|
||||
}
|
||||
else if (tokenType == IntegerTokenVal || tokenType == FloatTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::darkGreen);
|
||||
tf.setFontWeight(QFont::Bold);
|
||||
}
|
||||
else if (tokenType == StringVarTokenVal ||
|
||||
tokenType == StringAryVarTokenVal ||
|
||||
tokenType == IntVarTokenVal ||
|
||||
tokenType == IntAryVarTokenVal ||
|
||||
tokenType == FloatVarTokenVal ||
|
||||
tokenType == FloatAryVarTokenVal)
|
||||
{
|
||||
tf.setFontWeight(QFont::Bold);
|
||||
tf.setForeground(Qt::darkMagenta);
|
||||
}
|
||||
else if (tokenType == RemStringTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::darkGray);
|
||||
tf.setFontUnderline(true);
|
||||
}
|
||||
else if (tokenType == DataStringTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::darkRed);
|
||||
}
|
||||
else if (tokenType == ControlCharTokenVal)
|
||||
{
|
||||
// Inverse of StringTokenVal
|
||||
tf.setForeground(Qt::white);
|
||||
tf.setBackground(Qt::blue);
|
||||
}
|
||||
|
||||
return tf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ApplesoftToken::makeTextCharFormats()
|
||||
{
|
||||
// TCFDefault,
|
||||
// TCFCtrlChar,
|
||||
// TCFAscii,
|
||||
// TCFFunction,
|
||||
// TCFOperator,
|
||||
// TCFUnusedToken,
|
||||
// TCFNumber,
|
||||
// TCFString,
|
||||
// TCFVariable,
|
||||
// TCFDataString,
|
||||
// TCFRemString,
|
||||
// TCFUnknown
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ApplesoftToken::initializeTokenTable()
|
||||
{
|
||||
m_tokens[ASEnd] = " END "; m_tokens[ASFor] = " FOR ";
|
||||
m_tokens[ASNext] = " NEXT "; m_tokens[ASData] = " DATA ";
|
||||
m_tokens[ASInput] = " INPUT "; m_tokens[ASDel] = " DEL ";
|
||||
m_tokens[ASDim] = " DIM "; m_tokens[ASRead] = " READ ";
|
||||
m_tokens[ASGr] = " GR "; m_tokens[ASText] = " TEXT ";
|
||||
m_tokens[ASPr] = " PR# "; m_tokens[ASIn] = " IN# ";
|
||||
m_tokens[ASCall] = " CALL "; m_tokens[ASPlot] = " PLOT ";
|
||||
m_tokens[ASHlin] = " HLIN "; m_tokens[ASVlin] = " VLIN ";
|
||||
m_tokens[ASHgr2] = " HGR2 "; m_tokens[ASHgr] = " HGR ";
|
||||
m_tokens[ASHcolor] = " HCOLOR= "; m_tokens[ASHplot] = " HPLOT ";
|
||||
m_tokens[ASDraw] = " DRAW "; m_tokens[ASXdraw] = " XDRAW ";
|
||||
m_tokens[ASHtab] = " HTAB "; m_tokens[ASHome] = " HOME ";
|
||||
m_tokens[ASRot] = " ROT= "; m_tokens[ASScale] = " SCALE= ";
|
||||
m_tokens[ASShload] = " SHLOAD "; m_tokens[ASTrace] = " TRACE ";
|
||||
m_tokens[ASNotrace] = " NOTRACE "; m_tokens[ASNormal] = " NORMAL ";
|
||||
m_tokens[ASInverse] = " INVERSE "; m_tokens[ASFlash] = " FLASH ";
|
||||
m_tokens[ASColor] = " COLOR= "; m_tokens[ASPop] = " POP ";
|
||||
m_tokens[ASVtab] = " VTAB "; m_tokens[ASHimem] = " HIMEM: ";
|
||||
m_tokens[ASLomem] = " LOMEM: "; m_tokens[ASOnerr] = " ONERR ";
|
||||
m_tokens[ASResume] = " RESUME "; m_tokens[ASRecall] = " RECALL ";
|
||||
m_tokens[ASStore] = " STORE "; m_tokens[ASSpeed] = " SPEED= ";
|
||||
m_tokens[ASLet] = " LET "; m_tokens[ASGoto] = " GOTO ";
|
||||
m_tokens[ASRun] = " RUN "; m_tokens[ASIf] = " IF ";
|
||||
m_tokens[ASRestore] = " RESTORE "; m_tokens[ASAMP] = " & ";
|
||||
m_tokens[ASGosub] = " GOSUB "; m_tokens[ASReturn] = " RETURN ";
|
||||
m_tokens[ASRem] = " REM "; m_tokens[ASStop] = " STOP ";
|
||||
m_tokens[ASOn] = " ON "; m_tokens[ASWait] = " WAIT ";
|
||||
m_tokens[ASLoad] = " LOAD "; m_tokens[ASSave] = " SAVE ";
|
||||
m_tokens[ASDef] = " DEF "; m_tokens[ASPoke] = " POKE ";
|
||||
m_tokens[ASPrint] = " PRINT "; m_tokens[ASCont] = " CONT ";
|
||||
m_tokens[ASList] = " LIST "; m_tokens[ASClear] = " CLEAR ";
|
||||
m_tokens[ASGet] = " GET "; m_tokens[ASNew] = " NEW ";
|
||||
m_tokens[ASTab] = " TAB("; m_tokens[ASTo] = " TO ";
|
||||
m_tokens[ASFn] = " FN "; m_tokens[ASSpc] = " SPC( ";
|
||||
m_tokens[ASThen] = " THEN "; m_tokens[ASAt] = " AT ";
|
||||
m_tokens[ASNot] = " NOT "; m_tokens[ASStep] = " STEP ";
|
||||
m_tokens[ASPLUS] = " + "; m_tokens[ASMINUS] = " - ";
|
||||
m_tokens[ASASTERISK] = " * "; m_tokens[ASSLASH] = " / ";
|
||||
m_tokens[ASCARET] = " ^ "; m_tokens[ASAnd] = " AND ";
|
||||
m_tokens[ASOr] = " OR "; m_tokens[ASGREATER] = " > ";
|
||||
m_tokens[ASEQUAL] = " = "; m_tokens[ASLESS] = " < ";
|
||||
m_tokens[ASSgn] = " SGN"; m_tokens[ASInt] = " INT";
|
||||
m_tokens[ASAbs] = " ABS"; m_tokens[ASUsr] = " USR";
|
||||
m_tokens[ASFre] = " FRE"; m_tokens[ASScrn] = " SCRN( ";
|
||||
m_tokens[ASPdl] = " PDL"; m_tokens[ASPos] = " POS";
|
||||
m_tokens[ASSqr] = " SQR"; m_tokens[ASRnd] = " RND";
|
||||
m_tokens[ASLog] = " LOG"; m_tokens[ASExp] = " EXP";
|
||||
m_tokens[ASCos] = " COS"; m_tokens[ASSin] = " SIN";
|
||||
m_tokens[ASTan] = " TAN"; m_tokens[ASAtn] = " ATN";
|
||||
m_tokens[ASPeek] = " PEEK"; m_tokens[ASLen] = " LEN";
|
||||
m_tokens[ASStr] = " STR$"; m_tokens[ASVal] = " VAL";
|
||||
m_tokens[ASAsc] = " ASC"; m_tokens[ASChr] = " CHR$";
|
||||
m_tokens[ASLeft] = " LEFT$ "; m_tokens[ASRight] = " RIGHT$ ";
|
||||
m_tokens[ASMid] = " MID$ ";
|
||||
m_tokens[AS_EB] = "{Token 0xEB} "; m_tokens[AS_EC] = "{Token 0xEC} ";
|
||||
m_tokens[AS_ED] = "{Token 0xED} "; m_tokens[AS_EE] = "{Token 0xEE} ";
|
||||
m_tokens[AS_EF] = "{Token 0xEF} "; m_tokens[AS_F0] = "{Token 0xF0} ";
|
||||
m_tokens[AS_F1] = "{Token 0xF1} "; m_tokens[AS_F2] = "{Token 0xF2} ";
|
||||
m_tokens[AS_F3] = "{Token 0xF3} "; m_tokens[AS_F4] = "{Token 0xF4} ";
|
||||
m_tokens[AS_F5] = "{Token 0xF5} "; m_tokens[AS_F6] = "{Token 0xF6} ";
|
||||
m_tokens[AS_F7] = "{Token 0xF7} "; m_tokens[AS_F8] = "{Token 0xF8} ";
|
||||
m_tokens[AS_F9] = "{Token 0xF9} "; m_tokens[AS_FA] = "{Token 0xFA} ";
|
||||
m_tokens[AS_FB] = "{Token 0xFB} "; m_tokens[AS_FC] = "{Token 0xFC} ";
|
||||
m_tokens[AS_FD] = "{Token 0xFD} "; m_tokens[AS_FE] = "{Token 0xFE} ";
|
||||
m_tokens[AS_FF] = "{Token 0xFF} ";
|
||||
}
|
||||
|
||||
const quint16 ApplesoftToken::ASEnd = 0x80; const quint16 ApplesoftToken::ASFor = 0x81;
|
||||
const quint16 ApplesoftToken::ASNext = 0x82; const quint16 ApplesoftToken::ASData = 0x83;
|
||||
const quint16 ApplesoftToken::ASInput = 0x84; const quint16 ApplesoftToken::ASDel = 0x85;
|
||||
const quint16 ApplesoftToken::ASDim = 0x86; const quint16 ApplesoftToken::ASRead = 0x87;
|
||||
const quint16 ApplesoftToken::ASGr = 0x88; const quint16 ApplesoftToken::ASText = 0x89;
|
||||
const quint16 ApplesoftToken::ASPr = 0x8A; const quint16 ApplesoftToken::ASIn = 0x8B;
|
||||
const quint16 ApplesoftToken::ASCall = 0x8C; const quint16 ApplesoftToken::ASPlot = 0x8D;
|
||||
const quint16 ApplesoftToken::ASHlin = 0x8E; const quint16 ApplesoftToken::ASVlin = 0x8F;
|
||||
|
||||
const quint16 ApplesoftToken::ASHgr2 = 0x90; const quint16 ApplesoftToken::ASHgr = 0x91;
|
||||
const quint16 ApplesoftToken::ASHcolor = 0x92; const quint16 ApplesoftToken::ASHplot = 0x93;
|
||||
const quint16 ApplesoftToken::ASDraw = 0x94; const quint16 ApplesoftToken::ASXdraw = 0x95;
|
||||
const quint16 ApplesoftToken::ASHtab = 0x96; const quint16 ApplesoftToken::ASHome = 0x97;
|
||||
const quint16 ApplesoftToken::ASRot = 0x98; const quint16 ApplesoftToken::ASScale = 0x99;
|
||||
const quint16 ApplesoftToken::ASShload = 0x9A; const quint16 ApplesoftToken::ASTrace = 0x9B;
|
||||
const quint16 ApplesoftToken::ASNotrace = 0x9C; const quint16 ApplesoftToken::ASNormal = 0x9D;
|
||||
const quint16 ApplesoftToken::ASInverse = 0x9E; const quint16 ApplesoftToken::ASFlash = 0x9F;
|
||||
|
||||
const quint16 ApplesoftToken::ASColor = 0xA0; const quint16 ApplesoftToken::ASPop = 0xA1;
|
||||
const quint16 ApplesoftToken::ASVtab = 0xA2; const quint16 ApplesoftToken::ASHimem = 0xA3;
|
||||
const quint16 ApplesoftToken::ASLomem = 0xA4; const quint16 ApplesoftToken::ASOnerr = 0xA5;
|
||||
const quint16 ApplesoftToken::ASResume = 0xA6; const quint16 ApplesoftToken::ASRecall = 0xA7;
|
||||
const quint16 ApplesoftToken::ASStore = 0xA8; const quint16 ApplesoftToken::ASSpeed = 0xA9;
|
||||
const quint16 ApplesoftToken::ASLet = 0xAA; const quint16 ApplesoftToken::ASGoto = 0xAB;
|
||||
const quint16 ApplesoftToken::ASRun = 0xAC; const quint16 ApplesoftToken::ASIf = 0xAD;
|
||||
const quint16 ApplesoftToken::ASRestore = 0xAE; const quint16 ApplesoftToken::ASAMP = 0xAF;
|
||||
|
||||
const quint16 ApplesoftToken::ASGosub = 0xB0; const quint16 ApplesoftToken::ASReturn = 0xB1;
|
||||
const quint16 ApplesoftToken::ASRem = 0xB2; const quint16 ApplesoftToken::ASStop = 0xB3;
|
||||
const quint16 ApplesoftToken::ASOn = 0xB4; const quint16 ApplesoftToken::ASWait = 0xB5;
|
||||
const quint16 ApplesoftToken::ASLoad = 0xB6; const quint16 ApplesoftToken::ASSave = 0xB7;
|
||||
const quint16 ApplesoftToken::ASDef = 0xB8; const quint16 ApplesoftToken::ASPoke = 0xB9;
|
||||
const quint16 ApplesoftToken::ASPrint = 0xBA; const quint16 ApplesoftToken::ASCont = 0xBB;
|
||||
const quint16 ApplesoftToken::ASList = 0xBC; const quint16 ApplesoftToken::ASClear = 0xBD;
|
||||
const quint16 ApplesoftToken::ASGet = 0xBE; const quint16 ApplesoftToken::ASNew = 0xBF;
|
||||
|
||||
const quint16 ApplesoftToken::ASTab = 0xC0; const quint16 ApplesoftToken::ASTo = 0xC1;
|
||||
const quint16 ApplesoftToken::ASFn = 0xC2; const quint16 ApplesoftToken::ASSpc = 0xC3;
|
||||
const quint16 ApplesoftToken::ASThen = 0xC4; const quint16 ApplesoftToken::ASAt = 0xC5;
|
||||
const quint16 ApplesoftToken::ASNot = 0xC6; const quint16 ApplesoftToken::ASStep = 0xC7;
|
||||
const quint16 ApplesoftToken::ASPLUS = 0xC8; const quint16 ApplesoftToken::ASMINUS = 0xC9;
|
||||
const quint16 ApplesoftToken::ASASTERISK = 0xCA; const quint16 ApplesoftToken::ASSLASH = 0xCB;
|
||||
const quint16 ApplesoftToken::ASCARET = 0xCC; const quint16 ApplesoftToken::ASAnd = 0xCD;
|
||||
const quint16 ApplesoftToken::ASOr = 0xCE; const quint16 ApplesoftToken::ASGREATER = 0xCF;
|
||||
|
||||
const quint16 ApplesoftToken::ASEQUAL = 0xD0; const quint16 ApplesoftToken::ASLESS = 0xD1;
|
||||
const quint16 ApplesoftToken::ASSgn = 0xD2; const quint16 ApplesoftToken::ASInt = 0xD3;
|
||||
const quint16 ApplesoftToken::ASAbs = 0xD4; const quint16 ApplesoftToken::ASUsr = 0xD5;
|
||||
const quint16 ApplesoftToken::ASFre = 0xD6; const quint16 ApplesoftToken::ASScrn = 0xD7;
|
||||
const quint16 ApplesoftToken::ASPdl = 0xD8; const quint16 ApplesoftToken::ASPos = 0xD9;
|
||||
const quint16 ApplesoftToken::ASSqr = 0xDA; const quint16 ApplesoftToken::ASRnd = 0xDB;
|
||||
const quint16 ApplesoftToken::ASLog = 0xDC; const quint16 ApplesoftToken::ASExp = 0xDD;
|
||||
const quint16 ApplesoftToken::ASCos = 0xDE; const quint16 ApplesoftToken::ASSin = 0xDF;
|
||||
|
||||
const quint16 ApplesoftToken::ASTan = 0xE0; const quint16 ApplesoftToken::ASAtn = 0xE1;
|
||||
const quint16 ApplesoftToken::ASPeek = 0xE2; const quint16 ApplesoftToken::ASLen = 0xE3;
|
||||
const quint16 ApplesoftToken::ASStr = 0xE4; const quint16 ApplesoftToken::ASVal = 0xE5;
|
||||
const quint16 ApplesoftToken::ASAsc = 0xE6; const quint16 ApplesoftToken::ASChr = 0xE7;
|
||||
const quint16 ApplesoftToken::ASLeft = 0xE8; const quint16 ApplesoftToken::ASRight = 0xE9;
|
||||
const quint16 ApplesoftToken::ASMid = 0xEA; const quint16 ApplesoftToken::AS_EB = 0xEB;
|
||||
const quint16 ApplesoftToken::AS_EC = 0xEC; const quint16 ApplesoftToken::AS_ED = 0xED;
|
||||
const quint16 ApplesoftToken::AS_EE = 0xEE; const quint16 ApplesoftToken::AS_EF = 0xEF;
|
||||
|
||||
const quint16 ApplesoftToken::AS_F0 = 0xF0; const quint16 ApplesoftToken::AS_F1 = 0xF1;
|
||||
const quint16 ApplesoftToken::AS_F2 = 0xF2; const quint16 ApplesoftToken::AS_F3 = 0xF3;
|
||||
const quint16 ApplesoftToken::AS_F4 = 0xF4; const quint16 ApplesoftToken::AS_F5 = 0xF5;
|
||||
const quint16 ApplesoftToken::AS_F6 = 0xF6; const quint16 ApplesoftToken::AS_F7 = 0xF7;
|
||||
const quint16 ApplesoftToken::AS_F8 = 0xF8; const quint16 ApplesoftToken::AS_F9 = 0xF9;
|
||||
const quint16 ApplesoftToken::AS_FA = 0xFA; const quint16 ApplesoftToken::AS_FB = 0xFB;
|
||||
const quint16 ApplesoftToken::AS_FC = 0xFC; const quint16 ApplesoftToken::AS_FD = 0xFD;
|
||||
const quint16 ApplesoftToken::AS_FE = 0xFE; const quint16 ApplesoftToken::AS_FF = 0xFF;
|
||||
#include "applesofttoken.h"
|
||||
|
||||
QMap<quint16, QString> ApplesoftToken::m_tokens = QMap<quint16, QString>();
|
||||
|
||||
ApplesoftToken::ApplesoftToken()
|
||||
{
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
setTokenId(DefaultTokenVal);
|
||||
}
|
||||
|
||||
ApplesoftToken::ApplesoftToken(quint16 id)
|
||||
{
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
setTokenId(id);
|
||||
}
|
||||
|
||||
ApplesoftToken::ApplesoftToken(quint16 id, QVariant payload)
|
||||
{
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
setTokenId(id);
|
||||
setValue(payload);
|
||||
}
|
||||
|
||||
void ApplesoftToken::setTokenId(quint16 id)
|
||||
{
|
||||
m_token_id = id;
|
||||
m_token_type = UNKNOWN_TOKEN;
|
||||
m_command_type = NONE;
|
||||
|
||||
if (id <= 0x7f) {
|
||||
setValue(id);
|
||||
m_token_type = ASCIICHAR_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id <= 0xC7) {
|
||||
setValue(id);
|
||||
m_token_type = APPLESOFT_TOKEN;
|
||||
m_command_type = COMMAND;
|
||||
} else if (id <= 0xD1) {
|
||||
setValue(id);
|
||||
m_token_type = APPLESOFT_TOKEN;
|
||||
m_command_type = OPERATOR;
|
||||
} else if (id <= 0xEA) {
|
||||
setValue(id);
|
||||
m_token_type = APPLESOFT_TOKEN;
|
||||
m_command_type = FUNCTION;
|
||||
} else if (id <= 0xFF) {
|
||||
setValue(id);
|
||||
m_token_type = UNDEFINED_APPLESOFT_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == StringTokenVal) {
|
||||
m_token_type = STRING_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == RemStringTokenVal) {
|
||||
m_token_type = REM_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == DataStringTokenVal) {
|
||||
m_token_type = DATASTRING_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == IntegerTokenVal) {
|
||||
m_token_type = INTEGER_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == FloatTokenVal) {
|
||||
m_token_type = FLOAT_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == IntVarTokenVal) {
|
||||
m_token_type = INT_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == IntAryVarTokenVal) {
|
||||
m_token_type = INT_ARY_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == FloatVarTokenVal) {
|
||||
m_token_type = FLOAT_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == FloatAryVarTokenVal) {
|
||||
m_token_type = FLOAT_ARY_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == StringVarTokenVal) {
|
||||
m_token_type = STRING_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id == StringAryVarTokenVal) {
|
||||
m_token_type = STRING_ARY_VARIABLE_TOKEN;
|
||||
m_command_type = NONE;
|
||||
} else if (id >= 0xe000 && id < 0xf000) {
|
||||
m_token_type = OPTIONAL_FORMAT_TOKEN;
|
||||
m_command_type = OPTIONAL_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplesoftToken::setValue(QVariant value)
|
||||
{
|
||||
m_payload = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString ApplesoftToken::getRawPrintableString() const
|
||||
{
|
||||
if (m_token_id == DefaultTokenVal) {
|
||||
return "";
|
||||
} else if (m_token_id == 0x00) {
|
||||
return "";
|
||||
} else if (m_token_id <= 0x7f) {
|
||||
return QString((m_token_id));
|
||||
} else if (m_token_id <= 0xff) {
|
||||
return m_tokens[m_token_id];
|
||||
} else if (m_token_id == StringTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == RemStringTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == DataStringTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == IntegerTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == FloatTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == IntVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == IntAryVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == FloatVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == FloatAryVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == StringVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id == StringAryVarTokenVal) {
|
||||
return getStringValue();
|
||||
} else if (m_token_id >= 0xe000 && m_token_id < 0xf000) {
|
||||
return "";
|
||||
} else {
|
||||
return "[temp undefined]";
|
||||
}
|
||||
}
|
||||
|
||||
QTextCharFormat ApplesoftToken::defaultTextFormat()
|
||||
{
|
||||
QTextCharFormat tf; // Default
|
||||
tf.setForeground(Qt::black);
|
||||
return tf;
|
||||
}
|
||||
|
||||
QTextCharFormat ApplesoftToken::defaultInverseTextFormat()
|
||||
{
|
||||
QTextCharFormat tf;
|
||||
tf.setForeground(Qt::white);
|
||||
tf.setBackground(Qt::black);
|
||||
return tf;
|
||||
}
|
||||
|
||||
QTextCharFormat ApplesoftToken::textFormat(quint16 tokenType)
|
||||
{
|
||||
QTextCharFormat tf = defaultTextFormat();
|
||||
|
||||
if (tokenType < 0x80) // Ascii
|
||||
{
|
||||
tf.setForeground(Qt::black);
|
||||
}
|
||||
else if (tokenType < 0x100) // Applesoft Tokens
|
||||
{
|
||||
tf.setForeground(Qt::black);
|
||||
}
|
||||
else if (tokenType == StringTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::blue);
|
||||
tf.setFontWeight(QFont::Bold);
|
||||
}
|
||||
else if (tokenType == IntegerTokenVal || tokenType == FloatTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::darkGreen);
|
||||
tf.setFontWeight(QFont::Bold);
|
||||
}
|
||||
else if (tokenType == StringVarTokenVal ||
|
||||
tokenType == StringAryVarTokenVal ||
|
||||
tokenType == IntVarTokenVal ||
|
||||
tokenType == IntAryVarTokenVal ||
|
||||
tokenType == FloatVarTokenVal ||
|
||||
tokenType == FloatAryVarTokenVal)
|
||||
{
|
||||
tf.setFontWeight(QFont::Bold);
|
||||
tf.setForeground(Qt::darkMagenta);
|
||||
}
|
||||
else if (tokenType == RemStringTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::darkGray);
|
||||
tf.setFontUnderline(true);
|
||||
}
|
||||
else if (tokenType == DataStringTokenVal)
|
||||
{
|
||||
tf.setForeground(Qt::darkRed);
|
||||
}
|
||||
else if (tokenType == ControlCharTokenVal)
|
||||
{
|
||||
// Inverse of StringTokenVal
|
||||
tf.setForeground(Qt::white);
|
||||
tf.setBackground(Qt::blue);
|
||||
}
|
||||
|
||||
return tf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ApplesoftToken::makeTextCharFormats()
|
||||
{
|
||||
// TCFDefault,
|
||||
// TCFCtrlChar,
|
||||
// TCFAscii,
|
||||
// TCFFunction,
|
||||
// TCFOperator,
|
||||
// TCFUnusedToken,
|
||||
// TCFNumber,
|
||||
// TCFString,
|
||||
// TCFVariable,
|
||||
// TCFDataString,
|
||||
// TCFRemString,
|
||||
// TCFUnknown
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ApplesoftToken::initializeTokenTable()
|
||||
{
|
||||
m_tokens[ASEnd] = " END "; m_tokens[ASFor] = " FOR ";
|
||||
m_tokens[ASNext] = " NEXT "; m_tokens[ASData] = " DATA ";
|
||||
m_tokens[ASInput] = " INPUT "; m_tokens[ASDel] = " DEL ";
|
||||
m_tokens[ASDim] = " DIM "; m_tokens[ASRead] = " READ ";
|
||||
m_tokens[ASGr] = " GR "; m_tokens[ASText] = " TEXT ";
|
||||
m_tokens[ASPr] = " PR# "; m_tokens[ASIn] = " IN# ";
|
||||
m_tokens[ASCall] = " CALL "; m_tokens[ASPlot] = " PLOT ";
|
||||
m_tokens[ASHlin] = " HLIN "; m_tokens[ASVlin] = " VLIN ";
|
||||
m_tokens[ASHgr2] = " HGR2 "; m_tokens[ASHgr] = " HGR ";
|
||||
m_tokens[ASHcolor] = " HCOLOR= "; m_tokens[ASHplot] = " HPLOT ";
|
||||
m_tokens[ASDraw] = " DRAW "; m_tokens[ASXdraw] = " XDRAW ";
|
||||
m_tokens[ASHtab] = " HTAB "; m_tokens[ASHome] = " HOME ";
|
||||
m_tokens[ASRot] = " ROT= "; m_tokens[ASScale] = " SCALE= ";
|
||||
m_tokens[ASShload] = " SHLOAD "; m_tokens[ASTrace] = " TRACE ";
|
||||
m_tokens[ASNotrace] = " NOTRACE "; m_tokens[ASNormal] = " NORMAL ";
|
||||
m_tokens[ASInverse] = " INVERSE "; m_tokens[ASFlash] = " FLASH ";
|
||||
m_tokens[ASColor] = " COLOR= "; m_tokens[ASPop] = " POP ";
|
||||
m_tokens[ASVtab] = " VTAB "; m_tokens[ASHimem] = " HIMEM: ";
|
||||
m_tokens[ASLomem] = " LOMEM: "; m_tokens[ASOnerr] = " ONERR ";
|
||||
m_tokens[ASResume] = " RESUME "; m_tokens[ASRecall] = " RECALL ";
|
||||
m_tokens[ASStore] = " STORE "; m_tokens[ASSpeed] = " SPEED= ";
|
||||
m_tokens[ASLet] = " LET "; m_tokens[ASGoto] = " GOTO ";
|
||||
m_tokens[ASRun] = " RUN "; m_tokens[ASIf] = " IF ";
|
||||
m_tokens[ASRestore] = " RESTORE "; m_tokens[ASAMP] = " & ";
|
||||
m_tokens[ASGosub] = " GOSUB "; m_tokens[ASReturn] = " RETURN ";
|
||||
m_tokens[ASRem] = " REM "; m_tokens[ASStop] = " STOP ";
|
||||
m_tokens[ASOn] = " ON "; m_tokens[ASWait] = " WAIT ";
|
||||
m_tokens[ASLoad] = " LOAD "; m_tokens[ASSave] = " SAVE ";
|
||||
m_tokens[ASDef] = " DEF "; m_tokens[ASPoke] = " POKE ";
|
||||
m_tokens[ASPrint] = " PRINT "; m_tokens[ASCont] = " CONT ";
|
||||
m_tokens[ASList] = " LIST "; m_tokens[ASClear] = " CLEAR ";
|
||||
m_tokens[ASGet] = " GET "; m_tokens[ASNew] = " NEW ";
|
||||
m_tokens[ASTab] = " TAB("; m_tokens[ASTo] = " TO ";
|
||||
m_tokens[ASFn] = " FN "; m_tokens[ASSpc] = " SPC( ";
|
||||
m_tokens[ASThen] = " THEN "; m_tokens[ASAt] = " AT ";
|
||||
m_tokens[ASNot] = " NOT "; m_tokens[ASStep] = " STEP ";
|
||||
m_tokens[ASPLUS] = " + "; m_tokens[ASMINUS] = " - ";
|
||||
m_tokens[ASASTERISK] = " * "; m_tokens[ASSLASH] = " / ";
|
||||
m_tokens[ASCARET] = " ^ "; m_tokens[ASAnd] = " AND ";
|
||||
m_tokens[ASOr] = " OR "; m_tokens[ASGREATER] = " > ";
|
||||
m_tokens[ASEQUAL] = " = "; m_tokens[ASLESS] = " < ";
|
||||
m_tokens[ASSgn] = " SGN"; m_tokens[ASInt] = " INT";
|
||||
m_tokens[ASAbs] = " ABS"; m_tokens[ASUsr] = " USR";
|
||||
m_tokens[ASFre] = " FRE"; m_tokens[ASScrn] = " SCRN( ";
|
||||
m_tokens[ASPdl] = " PDL"; m_tokens[ASPos] = " POS";
|
||||
m_tokens[ASSqr] = " SQR"; m_tokens[ASRnd] = " RND";
|
||||
m_tokens[ASLog] = " LOG"; m_tokens[ASExp] = " EXP";
|
||||
m_tokens[ASCos] = " COS"; m_tokens[ASSin] = " SIN";
|
||||
m_tokens[ASTan] = " TAN"; m_tokens[ASAtn] = " ATN";
|
||||
m_tokens[ASPeek] = " PEEK"; m_tokens[ASLen] = " LEN";
|
||||
m_tokens[ASStr] = " STR$"; m_tokens[ASVal] = " VAL";
|
||||
m_tokens[ASAsc] = " ASC"; m_tokens[ASChr] = " CHR$";
|
||||
m_tokens[ASLeft] = " LEFT$ "; m_tokens[ASRight] = " RIGHT$ ";
|
||||
m_tokens[ASMid] = " MID$ ";
|
||||
m_tokens[AS_EB] = "{Token 0xEB} "; m_tokens[AS_EC] = "{Token 0xEC} ";
|
||||
m_tokens[AS_ED] = "{Token 0xED} "; m_tokens[AS_EE] = "{Token 0xEE} ";
|
||||
m_tokens[AS_EF] = "{Token 0xEF} "; m_tokens[AS_F0] = "{Token 0xF0} ";
|
||||
m_tokens[AS_F1] = "{Token 0xF1} "; m_tokens[AS_F2] = "{Token 0xF2} ";
|
||||
m_tokens[AS_F3] = "{Token 0xF3} "; m_tokens[AS_F4] = "{Token 0xF4} ";
|
||||
m_tokens[AS_F5] = "{Token 0xF5} "; m_tokens[AS_F6] = "{Token 0xF6} ";
|
||||
m_tokens[AS_F7] = "{Token 0xF7} "; m_tokens[AS_F8] = "{Token 0xF8} ";
|
||||
m_tokens[AS_F9] = "{Token 0xF9} "; m_tokens[AS_FA] = "{Token 0xFA} ";
|
||||
m_tokens[AS_FB] = "{Token 0xFB} "; m_tokens[AS_FC] = "{Token 0xFC} ";
|
||||
m_tokens[AS_FD] = "{Token 0xFD} "; m_tokens[AS_FE] = "{Token 0xFE} ";
|
||||
m_tokens[AS_FF] = "{Token 0xFF} ";
|
||||
}
|
||||
|
||||
const quint16 ApplesoftToken::ASEnd = 0x80; const quint16 ApplesoftToken::ASFor = 0x81;
|
||||
const quint16 ApplesoftToken::ASNext = 0x82; const quint16 ApplesoftToken::ASData = 0x83;
|
||||
const quint16 ApplesoftToken::ASInput = 0x84; const quint16 ApplesoftToken::ASDel = 0x85;
|
||||
const quint16 ApplesoftToken::ASDim = 0x86; const quint16 ApplesoftToken::ASRead = 0x87;
|
||||
const quint16 ApplesoftToken::ASGr = 0x88; const quint16 ApplesoftToken::ASText = 0x89;
|
||||
const quint16 ApplesoftToken::ASPr = 0x8A; const quint16 ApplesoftToken::ASIn = 0x8B;
|
||||
const quint16 ApplesoftToken::ASCall = 0x8C; const quint16 ApplesoftToken::ASPlot = 0x8D;
|
||||
const quint16 ApplesoftToken::ASHlin = 0x8E; const quint16 ApplesoftToken::ASVlin = 0x8F;
|
||||
|
||||
const quint16 ApplesoftToken::ASHgr2 = 0x90; const quint16 ApplesoftToken::ASHgr = 0x91;
|
||||
const quint16 ApplesoftToken::ASHcolor = 0x92; const quint16 ApplesoftToken::ASHplot = 0x93;
|
||||
const quint16 ApplesoftToken::ASDraw = 0x94; const quint16 ApplesoftToken::ASXdraw = 0x95;
|
||||
const quint16 ApplesoftToken::ASHtab = 0x96; const quint16 ApplesoftToken::ASHome = 0x97;
|
||||
const quint16 ApplesoftToken::ASRot = 0x98; const quint16 ApplesoftToken::ASScale = 0x99;
|
||||
const quint16 ApplesoftToken::ASShload = 0x9A; const quint16 ApplesoftToken::ASTrace = 0x9B;
|
||||
const quint16 ApplesoftToken::ASNotrace = 0x9C; const quint16 ApplesoftToken::ASNormal = 0x9D;
|
||||
const quint16 ApplesoftToken::ASInverse = 0x9E; const quint16 ApplesoftToken::ASFlash = 0x9F;
|
||||
|
||||
const quint16 ApplesoftToken::ASColor = 0xA0; const quint16 ApplesoftToken::ASPop = 0xA1;
|
||||
const quint16 ApplesoftToken::ASVtab = 0xA2; const quint16 ApplesoftToken::ASHimem = 0xA3;
|
||||
const quint16 ApplesoftToken::ASLomem = 0xA4; const quint16 ApplesoftToken::ASOnerr = 0xA5;
|
||||
const quint16 ApplesoftToken::ASResume = 0xA6; const quint16 ApplesoftToken::ASRecall = 0xA7;
|
||||
const quint16 ApplesoftToken::ASStore = 0xA8; const quint16 ApplesoftToken::ASSpeed = 0xA9;
|
||||
const quint16 ApplesoftToken::ASLet = 0xAA; const quint16 ApplesoftToken::ASGoto = 0xAB;
|
||||
const quint16 ApplesoftToken::ASRun = 0xAC; const quint16 ApplesoftToken::ASIf = 0xAD;
|
||||
const quint16 ApplesoftToken::ASRestore = 0xAE; const quint16 ApplesoftToken::ASAMP = 0xAF;
|
||||
|
||||
const quint16 ApplesoftToken::ASGosub = 0xB0; const quint16 ApplesoftToken::ASReturn = 0xB1;
|
||||
const quint16 ApplesoftToken::ASRem = 0xB2; const quint16 ApplesoftToken::ASStop = 0xB3;
|
||||
const quint16 ApplesoftToken::ASOn = 0xB4; const quint16 ApplesoftToken::ASWait = 0xB5;
|
||||
const quint16 ApplesoftToken::ASLoad = 0xB6; const quint16 ApplesoftToken::ASSave = 0xB7;
|
||||
const quint16 ApplesoftToken::ASDef = 0xB8; const quint16 ApplesoftToken::ASPoke = 0xB9;
|
||||
const quint16 ApplesoftToken::ASPrint = 0xBA; const quint16 ApplesoftToken::ASCont = 0xBB;
|
||||
const quint16 ApplesoftToken::ASList = 0xBC; const quint16 ApplesoftToken::ASClear = 0xBD;
|
||||
const quint16 ApplesoftToken::ASGet = 0xBE; const quint16 ApplesoftToken::ASNew = 0xBF;
|
||||
|
||||
const quint16 ApplesoftToken::ASTab = 0xC0; const quint16 ApplesoftToken::ASTo = 0xC1;
|
||||
const quint16 ApplesoftToken::ASFn = 0xC2; const quint16 ApplesoftToken::ASSpc = 0xC3;
|
||||
const quint16 ApplesoftToken::ASThen = 0xC4; const quint16 ApplesoftToken::ASAt = 0xC5;
|
||||
const quint16 ApplesoftToken::ASNot = 0xC6; const quint16 ApplesoftToken::ASStep = 0xC7;
|
||||
const quint16 ApplesoftToken::ASPLUS = 0xC8; const quint16 ApplesoftToken::ASMINUS = 0xC9;
|
||||
const quint16 ApplesoftToken::ASASTERISK = 0xCA; const quint16 ApplesoftToken::ASSLASH = 0xCB;
|
||||
const quint16 ApplesoftToken::ASCARET = 0xCC; const quint16 ApplesoftToken::ASAnd = 0xCD;
|
||||
const quint16 ApplesoftToken::ASOr = 0xCE; const quint16 ApplesoftToken::ASGREATER = 0xCF;
|
||||
|
||||
const quint16 ApplesoftToken::ASEQUAL = 0xD0; const quint16 ApplesoftToken::ASLESS = 0xD1;
|
||||
const quint16 ApplesoftToken::ASSgn = 0xD2; const quint16 ApplesoftToken::ASInt = 0xD3;
|
||||
const quint16 ApplesoftToken::ASAbs = 0xD4; const quint16 ApplesoftToken::ASUsr = 0xD5;
|
||||
const quint16 ApplesoftToken::ASFre = 0xD6; const quint16 ApplesoftToken::ASScrn = 0xD7;
|
||||
const quint16 ApplesoftToken::ASPdl = 0xD8; const quint16 ApplesoftToken::ASPos = 0xD9;
|
||||
const quint16 ApplesoftToken::ASSqr = 0xDA; const quint16 ApplesoftToken::ASRnd = 0xDB;
|
||||
const quint16 ApplesoftToken::ASLog = 0xDC; const quint16 ApplesoftToken::ASExp = 0xDD;
|
||||
const quint16 ApplesoftToken::ASCos = 0xDE; const quint16 ApplesoftToken::ASSin = 0xDF;
|
||||
|
||||
const quint16 ApplesoftToken::ASTan = 0xE0; const quint16 ApplesoftToken::ASAtn = 0xE1;
|
||||
const quint16 ApplesoftToken::ASPeek = 0xE2; const quint16 ApplesoftToken::ASLen = 0xE3;
|
||||
const quint16 ApplesoftToken::ASStr = 0xE4; const quint16 ApplesoftToken::ASVal = 0xE5;
|
||||
const quint16 ApplesoftToken::ASAsc = 0xE6; const quint16 ApplesoftToken::ASChr = 0xE7;
|
||||
const quint16 ApplesoftToken::ASLeft = 0xE8; const quint16 ApplesoftToken::ASRight = 0xE9;
|
||||
const quint16 ApplesoftToken::ASMid = 0xEA; const quint16 ApplesoftToken::AS_EB = 0xEB;
|
||||
const quint16 ApplesoftToken::AS_EC = 0xEC; const quint16 ApplesoftToken::AS_ED = 0xED;
|
||||
const quint16 ApplesoftToken::AS_EE = 0xEE; const quint16 ApplesoftToken::AS_EF = 0xEF;
|
||||
|
||||
const quint16 ApplesoftToken::AS_F0 = 0xF0; const quint16 ApplesoftToken::AS_F1 = 0xF1;
|
||||
const quint16 ApplesoftToken::AS_F2 = 0xF2; const quint16 ApplesoftToken::AS_F3 = 0xF3;
|
||||
const quint16 ApplesoftToken::AS_F4 = 0xF4; const quint16 ApplesoftToken::AS_F5 = 0xF5;
|
||||
const quint16 ApplesoftToken::AS_F6 = 0xF6; const quint16 ApplesoftToken::AS_F7 = 0xF7;
|
||||
const quint16 ApplesoftToken::AS_F8 = 0xF8; const quint16 ApplesoftToken::AS_F9 = 0xF9;
|
||||
const quint16 ApplesoftToken::AS_FA = 0xFA; const quint16 ApplesoftToken::AS_FB = 0xFB;
|
||||
const quint16 ApplesoftToken::AS_FC = 0xFC; const quint16 ApplesoftToken::AS_FD = 0xFD;
|
||||
const quint16 ApplesoftToken::AS_FE = 0xFE; const quint16 ApplesoftToken::AS_FF = 0xFF;
|
||||
|
@ -1,214 +1,214 @@
|
||||
#ifndef APPLESOFTTOKEN_H
|
||||
#define APPLESOFTTOKEN_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <QMap>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
enum TextCharFormatType {
|
||||
TCFDefault,
|
||||
TCFCtrlChar,
|
||||
TCFAscii,
|
||||
TCFFunction,
|
||||
TCFOperator,
|
||||
TCFUnusedToken,
|
||||
TCFNumber,
|
||||
TCFString,
|
||||
TCFVariable,
|
||||
TCFDataString,
|
||||
TCFRemString,
|
||||
TCFUnknown
|
||||
};
|
||||
|
||||
|
||||
class ApplesoftToken
|
||||
{
|
||||
public:
|
||||
|
||||
static const quint16 StringTokenVal = 0x100;
|
||||
static const quint16 RemStringTokenVal = 0x101;
|
||||
static const quint16 DataStringTokenVal = 0x102;
|
||||
|
||||
static const quint16 IntegerTokenVal = 0x103;
|
||||
static const quint16 FloatTokenVal = 0x104;
|
||||
|
||||
static const quint16 IntVarTokenVal = 0x105;
|
||||
static const quint16 IntAryVarTokenVal = 0x106;
|
||||
|
||||
static const quint16 FloatVarTokenVal = 0x107;
|
||||
static const quint16 FloatAryVarTokenVal = 0x108;
|
||||
|
||||
static const quint16 StringVarTokenVal = 0x109;
|
||||
static const quint16 StringAryVarTokenVal = 0x10A;
|
||||
|
||||
static const quint16 OptFmtLeadingSpaceTokenValue = 0xe000;
|
||||
static const quint16 OptFmtIndentLineBreakTokenValue = 0xe001;
|
||||
static const quint16 OptFmtIndentTabTokenValue = 0xe002;
|
||||
static const quint16 OptFmtIndentSpaceTokenValue = 0xe003;
|
||||
static const quint16 OptFmtFlagFlowTargetNextTokenValue = 0xe004;
|
||||
static const quint16 OptFmtReturnLineBreakTokenValue = 0xe005;
|
||||
|
||||
static const quint16 ControlCharTokenVal = 0xfffd;
|
||||
static const quint16 LineNumberTokenVal = 0xfffe;
|
||||
static const quint16 DefaultTokenVal = 0xffff;
|
||||
|
||||
|
||||
|
||||
static const quint16 ASEnd; static const quint16 ASFor;
|
||||
static const quint16 ASNext; static const quint16 ASData;
|
||||
static const quint16 ASInput; static const quint16 ASDel;
|
||||
static const quint16 ASDim; static const quint16 ASRead;
|
||||
static const quint16 ASGr; static const quint16 ASText;
|
||||
static const quint16 ASPr; static const quint16 ASIn;
|
||||
static const quint16 ASCall; static const quint16 ASPlot;
|
||||
static const quint16 ASHlin; static const quint16 ASVlin;
|
||||
|
||||
static const quint16 ASHgr2; static const quint16 ASHgr;
|
||||
static const quint16 ASHcolor; static const quint16 ASHplot;
|
||||
static const quint16 ASDraw; static const quint16 ASXdraw;
|
||||
static const quint16 ASHtab; static const quint16 ASHome;
|
||||
static const quint16 ASRot; static const quint16 ASScale;
|
||||
static const quint16 ASShload; static const quint16 ASTrace;
|
||||
static const quint16 ASNotrace; static const quint16 ASNormal;
|
||||
static const quint16 ASInverse; static const quint16 ASFlash;
|
||||
|
||||
static const quint16 ASColor; static const quint16 ASPop;
|
||||
static const quint16 ASVtab; static const quint16 ASHimem;
|
||||
static const quint16 ASLomem; static const quint16 ASOnerr;
|
||||
static const quint16 ASResume; static const quint16 ASRecall;
|
||||
static const quint16 ASStore; static const quint16 ASSpeed;
|
||||
static const quint16 ASLet; static const quint16 ASGoto;
|
||||
static const quint16 ASRun; static const quint16 ASIf;
|
||||
static const quint16 ASRestore; static const quint16 ASAMP;
|
||||
|
||||
static const quint16 ASGosub; static const quint16 ASReturn;
|
||||
static const quint16 ASRem; static const quint16 ASStop;
|
||||
static const quint16 ASOn; static const quint16 ASWait;
|
||||
static const quint16 ASLoad; static const quint16 ASSave;
|
||||
static const quint16 ASDef; static const quint16 ASPoke;
|
||||
static const quint16 ASPrint; static const quint16 ASCont;
|
||||
static const quint16 ASList; static const quint16 ASClear;
|
||||
static const quint16 ASGet; static const quint16 ASNew;
|
||||
|
||||
static const quint16 ASTab; static const quint16 ASTo;
|
||||
static const quint16 ASFn; static const quint16 ASSpc;
|
||||
static const quint16 ASThen; static const quint16 ASAt;
|
||||
static const quint16 ASNot; static const quint16 ASStep;
|
||||
static const quint16 ASPLUS; static const quint16 ASMINUS;
|
||||
static const quint16 ASASTERISK; static const quint16 ASSLASH;
|
||||
static const quint16 ASCARET; static const quint16 ASAnd;
|
||||
static const quint16 ASOr; static const quint16 ASGREATER;
|
||||
|
||||
static const quint16 ASEQUAL; static const quint16 ASLESS;
|
||||
static const quint16 ASSgn; static const quint16 ASInt;
|
||||
static const quint16 ASAbs; static const quint16 ASUsr;
|
||||
static const quint16 ASFre; static const quint16 ASScrn;
|
||||
static const quint16 ASPdl; static const quint16 ASPos;
|
||||
static const quint16 ASSqr; static const quint16 ASRnd;
|
||||
static const quint16 ASLog; static const quint16 ASExp;
|
||||
static const quint16 ASCos; static const quint16 ASSin;
|
||||
|
||||
static const quint16 ASTan; static const quint16 ASAtn;
|
||||
static const quint16 ASPeek; static const quint16 ASLen;
|
||||
static const quint16 ASStr; static const quint16 ASVal;
|
||||
static const quint16 ASAsc; static const quint16 ASChr;
|
||||
static const quint16 ASLeft; static const quint16 ASRight;
|
||||
static const quint16 ASMid; static const quint16 AS_EB;
|
||||
static const quint16 AS_EC; static const quint16 AS_ED;
|
||||
static const quint16 AS_EE; static const quint16 AS_EF;
|
||||
|
||||
static const quint16 AS_F0; static const quint16 AS_F1;
|
||||
static const quint16 AS_F2; static const quint16 AS_F3;
|
||||
static const quint16 AS_F4; static const quint16 AS_F5;
|
||||
static const quint16 AS_F6; static const quint16 AS_F7;
|
||||
static const quint16 AS_F8; static const quint16 AS_F9;
|
||||
static const quint16 AS_FA; static const quint16 AS_FB;
|
||||
static const quint16 AS_FC; static const quint16 AS_FD;
|
||||
static const quint16 AS_FE; static const quint16 AS_FF;
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN_TOKEN = 0x0,
|
||||
ASCIICHAR_TOKEN = 0x1,
|
||||
APPLESOFT_TOKEN = 0x2,
|
||||
UNDEFINED_APPLESOFT_TOKEN = 0x3,
|
||||
STRING_TOKEN = 0x4,
|
||||
INTEGER_TOKEN = 0x5,
|
||||
FLOAT_TOKEN = 0x6,
|
||||
DATASTRING_TOKEN = 0x7,
|
||||
REM_TOKEN = 0x8,
|
||||
INT_VARIABLE_TOKEN = 0x9,
|
||||
INT_ARY_VARIABLE_TOKEN = 0xA,
|
||||
FLOAT_VARIABLE_TOKEN = 0xB,
|
||||
FLOAT_ARY_VARIABLE_TOKEN = 0xC,
|
||||
STRING_VARIABLE_TOKEN = 0xD,
|
||||
STRING_ARY_VARIABLE_TOKEN = 0xE,
|
||||
OPTIONAL_FORMAT_TOKEN = 0xF
|
||||
} TokenType;
|
||||
|
||||
typedef enum {
|
||||
NONE,
|
||||
COMMAND,
|
||||
OPERATOR,
|
||||
FUNCTION,
|
||||
UNDEFINED_COMMAND,
|
||||
OPTIONAL_FORMAT
|
||||
} CommandType;
|
||||
|
||||
ApplesoftToken();
|
||||
ApplesoftToken(quint16 id);
|
||||
ApplesoftToken(quint16 id, QVariant payload);
|
||||
|
||||
void setTokenId(quint16 id);
|
||||
quint16 getTokenId() const { return m_token_id; }
|
||||
|
||||
void setValue(QVariant value);
|
||||
QVariant getValue() const { return m_payload; }
|
||||
|
||||
QByteArray getByteStringValue() const { return m_payload.toByteArray(); }
|
||||
QString getStringValue() const { return m_payload.toString(); }
|
||||
quint32 getUnsignedIntegerValue() const { return (quint32) (m_payload.toUInt() & 0xFFFFFFFF); }
|
||||
qint32 getIntegerValue() const { return (qint32) (m_payload.toInt() & 0xFFFFFFFF); }
|
||||
|
||||
quint16 getWordValue() const { return (quint16) (m_payload.toUInt() & 0xFFFF); }
|
||||
quint8 getByteValue() const { return (quint8) (m_payload.toUInt() & 0xFF); }
|
||||
|
||||
TokenType getTokenType() const { return m_token_type; }
|
||||
CommandType getCommandType() const { return m_command_type; }
|
||||
|
||||
QString getRawPrintableString() const;
|
||||
|
||||
QTextCharFormat textFormat()
|
||||
{
|
||||
return textFormat(m_token_id);
|
||||
}
|
||||
|
||||
static QTextCharFormat defaultTextFormat();
|
||||
static QTextCharFormat defaultInverseTextFormat();
|
||||
static QTextCharFormat textFormat(quint16 tokentype) ;
|
||||
|
||||
QString getStringForToken(quint8 token) {
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
return m_tokens[token];
|
||||
}
|
||||
|
||||
|
||||
bool isOptFmtToken() const { return (m_token_id >= 0xe000 && m_token_id < 0xf000); }
|
||||
|
||||
private:
|
||||
void makeTextCharFormats();
|
||||
|
||||
|
||||
static QMap<quint16, QString> m_tokens;
|
||||
|
||||
quint16 m_token_id;
|
||||
QString m_tokenname;
|
||||
QVariant m_payload;
|
||||
TokenType m_token_type;
|
||||
CommandType m_command_type;
|
||||
|
||||
static void initializeTokenTable();
|
||||
};
|
||||
|
||||
|
||||
#endif // APPLESOFTTOKEN_H
|
||||
#ifndef APPLESOFTTOKEN_H
|
||||
#define APPLESOFTTOKEN_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <QMap>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
enum TextCharFormatType {
|
||||
TCFDefault,
|
||||
TCFCtrlChar,
|
||||
TCFAscii,
|
||||
TCFFunction,
|
||||
TCFOperator,
|
||||
TCFUnusedToken,
|
||||
TCFNumber,
|
||||
TCFString,
|
||||
TCFVariable,
|
||||
TCFDataString,
|
||||
TCFRemString,
|
||||
TCFUnknown
|
||||
};
|
||||
|
||||
|
||||
class ApplesoftToken
|
||||
{
|
||||
public:
|
||||
|
||||
static const quint16 StringTokenVal = 0x100;
|
||||
static const quint16 RemStringTokenVal = 0x101;
|
||||
static const quint16 DataStringTokenVal = 0x102;
|
||||
|
||||
static const quint16 IntegerTokenVal = 0x103;
|
||||
static const quint16 FloatTokenVal = 0x104;
|
||||
|
||||
static const quint16 IntVarTokenVal = 0x105;
|
||||
static const quint16 IntAryVarTokenVal = 0x106;
|
||||
|
||||
static const quint16 FloatVarTokenVal = 0x107;
|
||||
static const quint16 FloatAryVarTokenVal = 0x108;
|
||||
|
||||
static const quint16 StringVarTokenVal = 0x109;
|
||||
static const quint16 StringAryVarTokenVal = 0x10A;
|
||||
|
||||
static const quint16 OptFmtLeadingSpaceTokenValue = 0xe000;
|
||||
static const quint16 OptFmtIndentLineBreakTokenValue = 0xe001;
|
||||
static const quint16 OptFmtIndentTabTokenValue = 0xe002;
|
||||
static const quint16 OptFmtIndentSpaceTokenValue = 0xe003;
|
||||
static const quint16 OptFmtFlagFlowTargetNextTokenValue = 0xe004;
|
||||
static const quint16 OptFmtReturnLineBreakTokenValue = 0xe005;
|
||||
|
||||
static const quint16 ControlCharTokenVal = 0xfffd;
|
||||
static const quint16 LineNumberTokenVal = 0xfffe;
|
||||
static const quint16 DefaultTokenVal = 0xffff;
|
||||
|
||||
|
||||
|
||||
static const quint16 ASEnd; static const quint16 ASFor;
|
||||
static const quint16 ASNext; static const quint16 ASData;
|
||||
static const quint16 ASInput; static const quint16 ASDel;
|
||||
static const quint16 ASDim; static const quint16 ASRead;
|
||||
static const quint16 ASGr; static const quint16 ASText;
|
||||
static const quint16 ASPr; static const quint16 ASIn;
|
||||
static const quint16 ASCall; static const quint16 ASPlot;
|
||||
static const quint16 ASHlin; static const quint16 ASVlin;
|
||||
|
||||
static const quint16 ASHgr2; static const quint16 ASHgr;
|
||||
static const quint16 ASHcolor; static const quint16 ASHplot;
|
||||
static const quint16 ASDraw; static const quint16 ASXdraw;
|
||||
static const quint16 ASHtab; static const quint16 ASHome;
|
||||
static const quint16 ASRot; static const quint16 ASScale;
|
||||
static const quint16 ASShload; static const quint16 ASTrace;
|
||||
static const quint16 ASNotrace; static const quint16 ASNormal;
|
||||
static const quint16 ASInverse; static const quint16 ASFlash;
|
||||
|
||||
static const quint16 ASColor; static const quint16 ASPop;
|
||||
static const quint16 ASVtab; static const quint16 ASHimem;
|
||||
static const quint16 ASLomem; static const quint16 ASOnerr;
|
||||
static const quint16 ASResume; static const quint16 ASRecall;
|
||||
static const quint16 ASStore; static const quint16 ASSpeed;
|
||||
static const quint16 ASLet; static const quint16 ASGoto;
|
||||
static const quint16 ASRun; static const quint16 ASIf;
|
||||
static const quint16 ASRestore; static const quint16 ASAMP;
|
||||
|
||||
static const quint16 ASGosub; static const quint16 ASReturn;
|
||||
static const quint16 ASRem; static const quint16 ASStop;
|
||||
static const quint16 ASOn; static const quint16 ASWait;
|
||||
static const quint16 ASLoad; static const quint16 ASSave;
|
||||
static const quint16 ASDef; static const quint16 ASPoke;
|
||||
static const quint16 ASPrint; static const quint16 ASCont;
|
||||
static const quint16 ASList; static const quint16 ASClear;
|
||||
static const quint16 ASGet; static const quint16 ASNew;
|
||||
|
||||
static const quint16 ASTab; static const quint16 ASTo;
|
||||
static const quint16 ASFn; static const quint16 ASSpc;
|
||||
static const quint16 ASThen; static const quint16 ASAt;
|
||||
static const quint16 ASNot; static const quint16 ASStep;
|
||||
static const quint16 ASPLUS; static const quint16 ASMINUS;
|
||||
static const quint16 ASASTERISK; static const quint16 ASSLASH;
|
||||
static const quint16 ASCARET; static const quint16 ASAnd;
|
||||
static const quint16 ASOr; static const quint16 ASGREATER;
|
||||
|
||||
static const quint16 ASEQUAL; static const quint16 ASLESS;
|
||||
static const quint16 ASSgn; static const quint16 ASInt;
|
||||
static const quint16 ASAbs; static const quint16 ASUsr;
|
||||
static const quint16 ASFre; static const quint16 ASScrn;
|
||||
static const quint16 ASPdl; static const quint16 ASPos;
|
||||
static const quint16 ASSqr; static const quint16 ASRnd;
|
||||
static const quint16 ASLog; static const quint16 ASExp;
|
||||
static const quint16 ASCos; static const quint16 ASSin;
|
||||
|
||||
static const quint16 ASTan; static const quint16 ASAtn;
|
||||
static const quint16 ASPeek; static const quint16 ASLen;
|
||||
static const quint16 ASStr; static const quint16 ASVal;
|
||||
static const quint16 ASAsc; static const quint16 ASChr;
|
||||
static const quint16 ASLeft; static const quint16 ASRight;
|
||||
static const quint16 ASMid; static const quint16 AS_EB;
|
||||
static const quint16 AS_EC; static const quint16 AS_ED;
|
||||
static const quint16 AS_EE; static const quint16 AS_EF;
|
||||
|
||||
static const quint16 AS_F0; static const quint16 AS_F1;
|
||||
static const quint16 AS_F2; static const quint16 AS_F3;
|
||||
static const quint16 AS_F4; static const quint16 AS_F5;
|
||||
static const quint16 AS_F6; static const quint16 AS_F7;
|
||||
static const quint16 AS_F8; static const quint16 AS_F9;
|
||||
static const quint16 AS_FA; static const quint16 AS_FB;
|
||||
static const quint16 AS_FC; static const quint16 AS_FD;
|
||||
static const quint16 AS_FE; static const quint16 AS_FF;
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN_TOKEN = 0x0,
|
||||
ASCIICHAR_TOKEN = 0x1,
|
||||
APPLESOFT_TOKEN = 0x2,
|
||||
UNDEFINED_APPLESOFT_TOKEN = 0x3,
|
||||
STRING_TOKEN = 0x4,
|
||||
INTEGER_TOKEN = 0x5,
|
||||
FLOAT_TOKEN = 0x6,
|
||||
DATASTRING_TOKEN = 0x7,
|
||||
REM_TOKEN = 0x8,
|
||||
INT_VARIABLE_TOKEN = 0x9,
|
||||
INT_ARY_VARIABLE_TOKEN = 0xA,
|
||||
FLOAT_VARIABLE_TOKEN = 0xB,
|
||||
FLOAT_ARY_VARIABLE_TOKEN = 0xC,
|
||||
STRING_VARIABLE_TOKEN = 0xD,
|
||||
STRING_ARY_VARIABLE_TOKEN = 0xE,
|
||||
OPTIONAL_FORMAT_TOKEN = 0xF
|
||||
} TokenType;
|
||||
|
||||
typedef enum {
|
||||
NONE,
|
||||
COMMAND,
|
||||
OPERATOR,
|
||||
FUNCTION,
|
||||
UNDEFINED_COMMAND,
|
||||
OPTIONAL_FORMAT
|
||||
} CommandType;
|
||||
|
||||
ApplesoftToken();
|
||||
ApplesoftToken(quint16 id);
|
||||
ApplesoftToken(quint16 id, QVariant payload);
|
||||
|
||||
void setTokenId(quint16 id);
|
||||
quint16 getTokenId() const { return m_token_id; }
|
||||
|
||||
void setValue(QVariant value);
|
||||
QVariant getValue() const { return m_payload; }
|
||||
|
||||
QByteArray getByteStringValue() const { return m_payload.toByteArray(); }
|
||||
QString getStringValue() const { return m_payload.toString(); }
|
||||
quint32 getUnsignedIntegerValue() const { return (quint32) (m_payload.toUInt() & 0xFFFFFFFF); }
|
||||
qint32 getIntegerValue() const { return (qint32) (m_payload.toInt() & 0xFFFFFFFF); }
|
||||
|
||||
quint16 getWordValue() const { return (quint16) (m_payload.toUInt() & 0xFFFF); }
|
||||
quint8 getByteValue() const { return (quint8) (m_payload.toUInt() & 0xFF); }
|
||||
|
||||
TokenType getTokenType() const { return m_token_type; }
|
||||
CommandType getCommandType() const { return m_command_type; }
|
||||
|
||||
QString getRawPrintableString() const;
|
||||
|
||||
QTextCharFormat textFormat()
|
||||
{
|
||||
return textFormat(m_token_id);
|
||||
}
|
||||
|
||||
static QTextCharFormat defaultTextFormat();
|
||||
static QTextCharFormat defaultInverseTextFormat();
|
||||
static QTextCharFormat textFormat(quint16 tokentype) ;
|
||||
|
||||
QString getStringForToken(quint8 token) {
|
||||
if (m_tokens.size() == 0) { initializeTokenTable(); }
|
||||
return m_tokens[token];
|
||||
}
|
||||
|
||||
|
||||
bool isOptFmtToken() const { return (m_token_id >= 0xe000 && m_token_id < 0xf000); }
|
||||
|
||||
private:
|
||||
void makeTextCharFormats();
|
||||
|
||||
|
||||
static QMap<quint16, QString> m_tokens;
|
||||
|
||||
quint16 m_token_id;
|
||||
QString m_tokenname;
|
||||
QVariant m_payload;
|
||||
TokenType m_token_type;
|
||||
CommandType m_command_type;
|
||||
|
||||
static void initializeTokenTable();
|
||||
};
|
||||
|
||||
|
||||
#endif // APPLESOFTTOKEN_H
|
||||
|
@ -1,136 +1,136 @@
|
||||
#include "AssemblerSymbolModel.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
AssemblerSymbolModel::AssemblerSymbolModel(QObject *parent, AssemblerSymbols *symbols)
|
||||
:QAbstractTableModel(parent)
|
||||
{
|
||||
setAssemblerSymbolsData(symbols);
|
||||
}
|
||||
|
||||
void AssemblerSymbolModel::setAssemblerSymbolsData(AssemblerSymbols *symbols)
|
||||
{
|
||||
assemblerSymbols = symbols;
|
||||
|
||||
if (assemblerSymbols)
|
||||
{
|
||||
connect(assemblerSymbols, &AssemblerSymbols::symbolAddedAt, this, &AssemblerSymbolModel::handleSymbolAddition);
|
||||
connect(assemblerSymbols, &AssemblerSymbols::symbolChangedAt, this, &AssemblerSymbolModel::handleSymbolChange);
|
||||
connect(assemblerSymbols, &AssemblerSymbols::symbolRemovedAt, this, &AssemblerSymbolModel::handleSymbolRemoval);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QVariant AssemblerSymbolModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (!assemblerSymbols) return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (section == 0)
|
||||
return "";
|
||||
|
||||
}
|
||||
}
|
||||
else // Orientation == Qt::Vertical
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return "0x"+uint16ToHex(assemblerSymbols->at(section).address);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int AssemblerSymbolModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
if (!assemblerSymbols) return 0;
|
||||
|
||||
return assemblerSymbols->numAssemblerSymbols();
|
||||
}
|
||||
|
||||
int AssemblerSymbolModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 2;
|
||||
}
|
||||
|
||||
QVariant AssemblerSymbolModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!assemblerSymbols) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
{
|
||||
QString val;
|
||||
if (assemblerSymbols->at(index.row()).symbolsize == SizeWord)
|
||||
{
|
||||
val = "WORD";
|
||||
}
|
||||
else if (assemblerSymbols->at(index.row()).symbolsize == SizeByte)
|
||||
{
|
||||
val = "BYTE";
|
||||
}
|
||||
return val;
|
||||
}
|
||||
else if (index.column() == 1)
|
||||
{
|
||||
return assemblerSymbols->at(index.row()).name;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool AssemblerSymbolModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!assemblerSymbols) return false;
|
||||
|
||||
if (data(index, role) != value) {
|
||||
if (index.column() == 1)
|
||||
{
|
||||
assemblerSymbols->symbolRefAt(index.row()).name = value.toString();
|
||||
}
|
||||
emit dataChanged(index, index, QVector<int>() << role);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags AssemblerSymbolModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
if (index.column() == 1)
|
||||
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
|
||||
else
|
||||
return QAbstractTableModel::flags(index);
|
||||
}
|
||||
|
||||
bool AssemblerSymbolModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
beginInsertRows(parent, row, row + count - 1);
|
||||
endInsertRows();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AssemblerSymbolModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
if (!assemblerSymbols) return false;
|
||||
bool success = false;
|
||||
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
for (int idx = 0; idx < count; idx++)
|
||||
{
|
||||
assemblerSymbols->removeSymbolAt(row);
|
||||
success = true;
|
||||
}
|
||||
endRemoveRows();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
#include "AssemblerSymbolModel.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
AssemblerSymbolModel::AssemblerSymbolModel(QObject *parent, AssemblerSymbols *symbols)
|
||||
:QAbstractTableModel(parent)
|
||||
{
|
||||
setAssemblerSymbolsData(symbols);
|
||||
}
|
||||
|
||||
void AssemblerSymbolModel::setAssemblerSymbolsData(AssemblerSymbols *symbols)
|
||||
{
|
||||
assemblerSymbols = symbols;
|
||||
|
||||
if (assemblerSymbols)
|
||||
{
|
||||
connect(assemblerSymbols, &AssemblerSymbols::symbolAddedAt, this, &AssemblerSymbolModel::handleSymbolAddition);
|
||||
connect(assemblerSymbols, &AssemblerSymbols::symbolChangedAt, this, &AssemblerSymbolModel::handleSymbolChange);
|
||||
connect(assemblerSymbols, &AssemblerSymbols::symbolRemovedAt, this, &AssemblerSymbolModel::handleSymbolRemoval);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QVariant AssemblerSymbolModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (!assemblerSymbols) return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (section == 0)
|
||||
return "";
|
||||
|
||||
}
|
||||
}
|
||||
else // Orientation == Qt::Vertical
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return "0x"+uint16ToHex(assemblerSymbols->at(section).address);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int AssemblerSymbolModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
if (!assemblerSymbols) return 0;
|
||||
|
||||
return assemblerSymbols->numAssemblerSymbols();
|
||||
}
|
||||
|
||||
int AssemblerSymbolModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 2;
|
||||
}
|
||||
|
||||
QVariant AssemblerSymbolModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!assemblerSymbols) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
{
|
||||
QString val;
|
||||
if (assemblerSymbols->at(index.row()).symbolsize == SizeWord)
|
||||
{
|
||||
val = "WORD";
|
||||
}
|
||||
else if (assemblerSymbols->at(index.row()).symbolsize == SizeByte)
|
||||
{
|
||||
val = "BYTE";
|
||||
}
|
||||
return val;
|
||||
}
|
||||
else if (index.column() == 1)
|
||||
{
|
||||
return assemblerSymbols->at(index.row()).name;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool AssemblerSymbolModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!assemblerSymbols) return false;
|
||||
|
||||
if (data(index, role) != value) {
|
||||
if (index.column() == 1)
|
||||
{
|
||||
assemblerSymbols->symbolRefAt(index.row()).name = value.toString();
|
||||
}
|
||||
emit dataChanged(index, index, QVector<int>() << role);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags AssemblerSymbolModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
if (index.column() == 1)
|
||||
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
|
||||
else
|
||||
return QAbstractTableModel::flags(index);
|
||||
}
|
||||
|
||||
bool AssemblerSymbolModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
beginInsertRows(parent, row, row + count - 1);
|
||||
endInsertRows();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AssemblerSymbolModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
if (!assemblerSymbols) return false;
|
||||
bool success = false;
|
||||
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
for (int idx = 0; idx < count; idx++)
|
||||
{
|
||||
assemblerSymbols->removeSymbolAt(row);
|
||||
success = true;
|
||||
}
|
||||
endRemoveRows();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,60 +1,60 @@
|
||||
#ifndef ASSEMBLERSYMBOLMODEL_H
|
||||
#define ASSEMBLERSYMBOLMODEL_H
|
||||
|
||||
|
||||
#include "AssemblerSymbols.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
||||
|
||||
|
||||
class AssemblerSymbolModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AssemblerSymbolModel(QObject *parent = 0, AssemblerSymbols *symbols = Q_NULLPTR);
|
||||
void setAssemblerSymbolsData(AssemblerSymbols *symbols);
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;//DONE
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Editable:
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
// Add data:
|
||||
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
// Remove data:
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void doTestData();
|
||||
|
||||
|
||||
protected slots:
|
||||
void handleSymbolAddition(int location) { insertRows(location,1); }
|
||||
void handleSymbolRemoval(int location) { removeRows(location, 1); }
|
||||
void handleSymbolChange(int location)
|
||||
{
|
||||
QModelIndex ind = createIndex(location,0);
|
||||
emit dataChanged(ind,ind,QVector<int>() << Qt::DisplayRole);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
AssemblerSymbols *assemblerSymbols;
|
||||
};
|
||||
|
||||
|
||||
#endif // ASSEMBLERSYMBOLMODEL_H
|
||||
#ifndef ASSEMBLERSYMBOLMODEL_H
|
||||
#define ASSEMBLERSYMBOLMODEL_H
|
||||
|
||||
|
||||
#include "AssemblerSymbols.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
||||
|
||||
|
||||
class AssemblerSymbolModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AssemblerSymbolModel(QObject *parent = 0, AssemblerSymbols *symbols = Q_NULLPTR);
|
||||
void setAssemblerSymbolsData(AssemblerSymbols *symbols);
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;//DONE
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Editable:
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
// Add data:
|
||||
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
// Remove data:
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void doTestData();
|
||||
|
||||
|
||||
protected slots:
|
||||
void handleSymbolAddition(int location) { insertRows(location,1); }
|
||||
void handleSymbolRemoval(int location) { removeRows(location, 1); }
|
||||
void handleSymbolChange(int location)
|
||||
{
|
||||
QModelIndex ind = createIndex(location,0);
|
||||
emit dataChanged(ind,ind,QVector<int>() << Qt::DisplayRole);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
AssemblerSymbols *assemblerSymbols;
|
||||
};
|
||||
|
||||
|
||||
#endif // ASSEMBLERSYMBOLMODEL_H
|
||||
|
@ -1,142 +1,142 @@
|
||||
#include "AssemblerSymbols.h"
|
||||
|
||||
|
||||
AssemblerSymbols::AssemblerSymbols(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int AssemblerSymbols::locationOfSymbolAtAddress(quint16 address)
|
||||
{
|
||||
// Assume list m_assemblerSymbols is sorted by address (it should be)
|
||||
QListIterator<AssemblerSymbol> it(m_assemblerSymbols);
|
||||
int idx = 0;
|
||||
while (it.hasNext())
|
||||
{
|
||||
AssemblerSymbol ep = it.next();
|
||||
if (ep.address == address) return idx;
|
||||
if (ep.address > address) return -1;
|
||||
idx++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool AssemblerSymbols::hasAssemSymbolAtAddress(quint16 address)
|
||||
{
|
||||
// Assume list m_assemblerSymbols is sorted by address (it should be)
|
||||
QListIterator<AssemblerSymbol> it(m_assemblerSymbols);
|
||||
while (it.hasNext())
|
||||
{
|
||||
AssemblerSymbol ep = it.next();
|
||||
if (ep.address == address) return true;
|
||||
if (ep.address > address) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AssemblerSymbols::editSymbol(int location, AssemblerSymbol newSymbol)
|
||||
{
|
||||
|
||||
if (m_assemblerSymbols.at(location).address == newSymbol.address)
|
||||
{
|
||||
m_assemblerSymbols[location].name = newSymbol.name;
|
||||
emit symbolChangedAt(location);
|
||||
}
|
||||
else
|
||||
{
|
||||
removeSymbolAt(location);
|
||||
addSymbol(newSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblerSymbols::addSymbol(AssemblerSymbol ep)
|
||||
{
|
||||
if (hasAssemSymbolAtAddress(ep.address)) return;
|
||||
|
||||
int idx = 0;
|
||||
for (; idx < m_assemblerSymbols.count(); idx++)
|
||||
{
|
||||
if (ep.address < m_assemblerSymbols[idx].address)
|
||||
break;
|
||||
}
|
||||
m_assemblerSymbols.insert(idx,ep);
|
||||
emit symbolAddedAt(idx);
|
||||
emit symbolAdded(ep,idx);
|
||||
}
|
||||
|
||||
void AssemblerSymbols::removeSymbolAt(int location)
|
||||
{
|
||||
m_assemblerSymbols.removeAt(location);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// STREAMING OPERATORS
|
||||
|
||||
QDataStream &AssemblerSymbols::read(QDataStream &dataStream)
|
||||
{
|
||||
quint8 version;
|
||||
dataStream >> version;
|
||||
if (version == 0)
|
||||
{
|
||||
dataStream >> m_assemblerSymbols;
|
||||
}
|
||||
else qWarning("Unhandled version of AssemSymbolModel (%d) found in QDataStream",version);
|
||||
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QDataStream &AssemblerSymbols::write(QDataStream &dataStream) const
|
||||
{
|
||||
quint8 version = 0; // Increment this and update read() if new items are added
|
||||
dataStream << version;
|
||||
dataStream << m_assemblerSymbols;
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const AssemblerSymbols &model)
|
||||
{
|
||||
return model.write(out);
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, AssemblerSymbols&model)
|
||||
{
|
||||
return model.read(in);
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const AssemblerSymbol &model)
|
||||
{
|
||||
out << model.address;
|
||||
out << model.name;
|
||||
out << (qint32) model.symbolsize;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, AssemblerSymbol &model)
|
||||
{
|
||||
in >> model.address;
|
||||
in >> model.name;
|
||||
qint32 size;
|
||||
in >> size;
|
||||
model.symbolsize = (SymbolSize) size;
|
||||
return in;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// TESTING
|
||||
|
||||
void AssemblerSymbols::doTestData()
|
||||
{
|
||||
AssemblerSymbol ep;
|
||||
ep.address = 0x0100;
|
||||
ep.name = "Test Symbol 1";
|
||||
addSymbol(ep);
|
||||
ep.address = 0x0200;
|
||||
ep.name = "Test Symbol 2";
|
||||
addSymbol(ep);
|
||||
ep.address = 0x0300;
|
||||
ep.name = "Test Symbol 3";
|
||||
addSymbol(ep);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include "AssemblerSymbols.h"
|
||||
|
||||
|
||||
AssemblerSymbols::AssemblerSymbols(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int AssemblerSymbols::locationOfSymbolAtAddress(quint16 address)
|
||||
{
|
||||
// Assume list m_assemblerSymbols is sorted by address (it should be)
|
||||
QListIterator<AssemblerSymbol> it(m_assemblerSymbols);
|
||||
int idx = 0;
|
||||
while (it.hasNext())
|
||||
{
|
||||
AssemblerSymbol ep = it.next();
|
||||
if (ep.address == address) return idx;
|
||||
if (ep.address > address) return -1;
|
||||
idx++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool AssemblerSymbols::hasAssemSymbolAtAddress(quint16 address)
|
||||
{
|
||||
// Assume list m_assemblerSymbols is sorted by address (it should be)
|
||||
QListIterator<AssemblerSymbol> it(m_assemblerSymbols);
|
||||
while (it.hasNext())
|
||||
{
|
||||
AssemblerSymbol ep = it.next();
|
||||
if (ep.address == address) return true;
|
||||
if (ep.address > address) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AssemblerSymbols::editSymbol(int location, AssemblerSymbol newSymbol)
|
||||
{
|
||||
|
||||
if (m_assemblerSymbols.at(location).address == newSymbol.address)
|
||||
{
|
||||
m_assemblerSymbols[location].name = newSymbol.name;
|
||||
emit symbolChangedAt(location);
|
||||
}
|
||||
else
|
||||
{
|
||||
removeSymbolAt(location);
|
||||
addSymbol(newSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblerSymbols::addSymbol(AssemblerSymbol ep)
|
||||
{
|
||||
if (hasAssemSymbolAtAddress(ep.address)) return;
|
||||
|
||||
int idx = 0;
|
||||
for (; idx < m_assemblerSymbols.count(); idx++)
|
||||
{
|
||||
if (ep.address < m_assemblerSymbols[idx].address)
|
||||
break;
|
||||
}
|
||||
m_assemblerSymbols.insert(idx,ep);
|
||||
emit symbolAddedAt(idx);
|
||||
emit symbolAdded(ep,idx);
|
||||
}
|
||||
|
||||
void AssemblerSymbols::removeSymbolAt(int location)
|
||||
{
|
||||
m_assemblerSymbols.removeAt(location);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// STREAMING OPERATORS
|
||||
|
||||
QDataStream &AssemblerSymbols::read(QDataStream &dataStream)
|
||||
{
|
||||
quint8 version;
|
||||
dataStream >> version;
|
||||
if (version == 0)
|
||||
{
|
||||
dataStream >> m_assemblerSymbols;
|
||||
}
|
||||
else qWarning("Unhandled version of AssemSymbolModel (%d) found in QDataStream",version);
|
||||
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QDataStream &AssemblerSymbols::write(QDataStream &dataStream) const
|
||||
{
|
||||
quint8 version = 0; // Increment this and update read() if new items are added
|
||||
dataStream << version;
|
||||
dataStream << m_assemblerSymbols;
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const AssemblerSymbols &model)
|
||||
{
|
||||
return model.write(out);
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, AssemblerSymbols&model)
|
||||
{
|
||||
return model.read(in);
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const AssemblerSymbol &model)
|
||||
{
|
||||
out << model.address;
|
||||
out << model.name;
|
||||
out << (qint32) model.symbolsize;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, AssemblerSymbol &model)
|
||||
{
|
||||
in >> model.address;
|
||||
in >> model.name;
|
||||
qint32 size;
|
||||
in >> size;
|
||||
model.symbolsize = (SymbolSize) size;
|
||||
return in;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// TESTING
|
||||
|
||||
void AssemblerSymbols::doTestData()
|
||||
{
|
||||
AssemblerSymbol ep;
|
||||
ep.address = 0x0100;
|
||||
ep.name = "Test Symbol 1";
|
||||
addSymbol(ep);
|
||||
ep.address = 0x0200;
|
||||
ep.name = "Test Symbol 2";
|
||||
addSymbol(ep);
|
||||
ep.address = 0x0300;
|
||||
ep.name = "Test Symbol 3";
|
||||
addSymbol(ep);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,60 +1,60 @@
|
||||
#ifndef ASSEMBLERSYMBOLS_H
|
||||
#define ASSEMBLERSYMBOLS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDataStream>
|
||||
|
||||
typedef enum {
|
||||
SizeUnknown = 0,
|
||||
SizeByte = 1,
|
||||
SizeWord = 2
|
||||
} SymbolSize;
|
||||
|
||||
struct AssemblerSymbol {
|
||||
quint16 address;
|
||||
QString name;
|
||||
SymbolSize symbolsize;
|
||||
};
|
||||
|
||||
|
||||
class AssemblerSymbols : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AssemblerSymbols(QObject *parent = 0);
|
||||
|
||||
bool hasAssemSymbolAtAddress(quint16 address);
|
||||
|
||||
const AssemblerSymbol &at(int location) const { return m_assemblerSymbols.at(location); }
|
||||
AssemblerSymbol &symbolRefAt(int location) { return m_assemblerSymbols[location]; }
|
||||
AssemblerSymbol &operator[](int location) { return m_assemblerSymbols[location]; }
|
||||
|
||||
void editSymbol(int at, AssemblerSymbol newSymbol);
|
||||
|
||||
QDataStream &read(QDataStream &dataStream);
|
||||
QDataStream &write(QDataStream &dataStream) const;
|
||||
|
||||
int numAssemblerSymbols() const { return m_assemblerSymbols.count(); }
|
||||
|
||||
void doTestData();
|
||||
|
||||
int locationOfSymbolAtAddress(quint16 address);
|
||||
signals:
|
||||
void symbolAdded(AssemblerSymbol &AssemblerSymbol, int location);
|
||||
void symbolAddedAt(int location);
|
||||
void symbolRemovedAt(int location);
|
||||
void symbolChangedAt(int location);
|
||||
|
||||
public slots:
|
||||
void addSymbol(AssemblerSymbol ep);
|
||||
void removeSymbolAt(int location);
|
||||
|
||||
protected:
|
||||
QList<AssemblerSymbol> m_assemblerSymbols;
|
||||
};
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const AssemblerSymbols &model);
|
||||
QDataStream &operator>>(QDataStream &in, AssemblerSymbols &model);
|
||||
|
||||
|
||||
#endif // ASSEMBLERSYMBOLS_H
|
||||
#ifndef ASSEMBLERSYMBOLS_H
|
||||
#define ASSEMBLERSYMBOLS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDataStream>
|
||||
|
||||
typedef enum {
|
||||
SizeUnknown = 0,
|
||||
SizeByte = 1,
|
||||
SizeWord = 2
|
||||
} SymbolSize;
|
||||
|
||||
struct AssemblerSymbol {
|
||||
quint16 address;
|
||||
QString name;
|
||||
SymbolSize symbolsize;
|
||||
};
|
||||
|
||||
|
||||
class AssemblerSymbols : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AssemblerSymbols(QObject *parent = 0);
|
||||
|
||||
bool hasAssemSymbolAtAddress(quint16 address);
|
||||
|
||||
const AssemblerSymbol &at(int location) const { return m_assemblerSymbols.at(location); }
|
||||
AssemblerSymbol &symbolRefAt(int location) { return m_assemblerSymbols[location]; }
|
||||
AssemblerSymbol &operator[](int location) { return m_assemblerSymbols[location]; }
|
||||
|
||||
void editSymbol(int at, AssemblerSymbol newSymbol);
|
||||
|
||||
QDataStream &read(QDataStream &dataStream);
|
||||
QDataStream &write(QDataStream &dataStream) const;
|
||||
|
||||
int numAssemblerSymbols() const { return m_assemblerSymbols.count(); }
|
||||
|
||||
void doTestData();
|
||||
|
||||
int locationOfSymbolAtAddress(quint16 address);
|
||||
signals:
|
||||
void symbolAdded(AssemblerSymbol &AssemblerSymbol, int location);
|
||||
void symbolAddedAt(int location);
|
||||
void symbolRemovedAt(int location);
|
||||
void symbolChangedAt(int location);
|
||||
|
||||
public slots:
|
||||
void addSymbol(AssemblerSymbol ep);
|
||||
void removeSymbolAt(int location);
|
||||
|
||||
protected:
|
||||
QList<AssemblerSymbol> m_assemblerSymbols;
|
||||
};
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const AssemblerSymbols &model);
|
||||
QDataStream &operator>>(QDataStream &in, AssemblerSymbols &model);
|
||||
|
||||
|
||||
#endif // ASSEMBLERSYMBOLS_H
|
||||
|
@ -1,134 +1,134 @@
|
||||
#include "EntryPointModel.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
|
||||
EntryPointModel::EntryPointModel(QObject *parent, EntryPoints *points)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
setEntryPointsData(points);
|
||||
}
|
||||
|
||||
void EntryPointModel::setEntryPointsData(EntryPoints *points)
|
||||
{
|
||||
entryPoints = points;
|
||||
|
||||
if (entryPoints)
|
||||
{
|
||||
connect(entryPoints, &EntryPoints::pointAddedAt, this, &EntryPointModel::handlePointAddition);
|
||||
connect(entryPoints, &EntryPoints::pointChangedAt, this, &EntryPointModel::handlePointChange);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QVariant EntryPointModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (!entryPoints) return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (section == 0)
|
||||
return "";
|
||||
|
||||
}
|
||||
}
|
||||
else // Orientation == Qt::Vertical
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return "0x"+uint16ToHex(entryPoints->at(section).address);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int EntryPointModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
if (!entryPoints) return 0;
|
||||
|
||||
return entryPoints->numEntryPoints();
|
||||
}
|
||||
|
||||
int EntryPointModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant EntryPointModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!entryPoints) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
{
|
||||
return entryPoints->at(index.row()).note;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool EntryPointModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!entryPoints) return false;
|
||||
|
||||
if (data(index, role) != value) {
|
||||
if (index.column() == 0)
|
||||
{
|
||||
entryPoints->pointRefAt(index.row()).note = value.toString();
|
||||
}
|
||||
emit dataChanged(index, index, QVector<int>() << role);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags EntryPointModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
if (index.column() == 0)
|
||||
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
|
||||
else
|
||||
return QAbstractTableModel::flags(index);
|
||||
}
|
||||
|
||||
bool EntryPointModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
beginInsertRows(parent, row, row + count - 1);
|
||||
endInsertRows();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntryPointModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
|
||||
if (!entryPoints) return false;
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
bool success = false;
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
for (int idx = 0; idx < count; idx++)
|
||||
{
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
entryPoints->removePointAt(row);
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
success = true;
|
||||
}
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
endRemoveRows();
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
#include "EntryPointModel.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
|
||||
EntryPointModel::EntryPointModel(QObject *parent, EntryPoints *points)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
setEntryPointsData(points);
|
||||
}
|
||||
|
||||
void EntryPointModel::setEntryPointsData(EntryPoints *points)
|
||||
{
|
||||
entryPoints = points;
|
||||
|
||||
if (entryPoints)
|
||||
{
|
||||
connect(entryPoints, &EntryPoints::pointAddedAt, this, &EntryPointModel::handlePointAddition);
|
||||
connect(entryPoints, &EntryPoints::pointChangedAt, this, &EntryPointModel::handlePointChange);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QVariant EntryPointModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (!entryPoints) return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (section == 0)
|
||||
return "";
|
||||
|
||||
}
|
||||
}
|
||||
else // Orientation == Qt::Vertical
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return "0x"+uint16ToHex(entryPoints->at(section).address);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int EntryPointModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
if (!entryPoints) return 0;
|
||||
|
||||
return entryPoints->numEntryPoints();
|
||||
}
|
||||
|
||||
int EntryPointModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant EntryPointModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!entryPoints) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
{
|
||||
return entryPoints->at(index.row()).note;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool EntryPointModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!entryPoints) return false;
|
||||
|
||||
if (data(index, role) != value) {
|
||||
if (index.column() == 0)
|
||||
{
|
||||
entryPoints->pointRefAt(index.row()).note = value.toString();
|
||||
}
|
||||
emit dataChanged(index, index, QVector<int>() << role);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags EntryPointModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
if (index.column() == 0)
|
||||
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
|
||||
else
|
||||
return QAbstractTableModel::flags(index);
|
||||
}
|
||||
|
||||
bool EntryPointModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
beginInsertRows(parent, row, row + count - 1);
|
||||
endInsertRows();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntryPointModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
|
||||
if (!entryPoints) return false;
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
bool success = false;
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
for (int idx = 0; idx < count; idx++)
|
||||
{
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
entryPoints->removePointAt(row);
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
success = true;
|
||||
}
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
endRemoveRows();
|
||||
qDebug() << __FILE__ << __LINE__;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,60 +1,60 @@
|
||||
#ifndef ENTRYPOINTMODEL_H
|
||||
#define ENTRYPOINTMODEL_H
|
||||
|
||||
#include "EntryPoints.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
||||
|
||||
|
||||
class EntryPointModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EntryPointModel(QObject *parent = 0, EntryPoints *points = Q_NULLPTR);
|
||||
void setEntryPointsData(EntryPoints *points);
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Editable:
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
// Add data:
|
||||
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
// Remove data:
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void doTestData();
|
||||
|
||||
|
||||
protected slots:
|
||||
void handlePointAddition(int location) { insertRows(location,1); }
|
||||
// void handlePointRemoval(int location) { removeRows(location, 1); }
|
||||
void handlePointChange(int location)
|
||||
{
|
||||
QModelIndex ind = createIndex(location,0);
|
||||
emit dataChanged(ind,ind,QVector<int>() << Qt::DisplayRole);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
EntryPoints *entryPoints;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // ENTRYPOINTMODEL_H
|
||||
#ifndef ENTRYPOINTMODEL_H
|
||||
#define ENTRYPOINTMODEL_H
|
||||
|
||||
#include "EntryPoints.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
||||
|
||||
|
||||
class EntryPointModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EntryPointModel(QObject *parent = 0, EntryPoints *points = Q_NULLPTR);
|
||||
void setEntryPointsData(EntryPoints *points);
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Editable:
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
// Add data:
|
||||
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
// Remove data:
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void doTestData();
|
||||
|
||||
|
||||
protected slots:
|
||||
void handlePointAddition(int location) { insertRows(location,1); }
|
||||
// void handlePointRemoval(int location) { removeRows(location, 1); }
|
||||
void handlePointChange(int location)
|
||||
{
|
||||
QModelIndex ind = createIndex(location,0);
|
||||
emit dataChanged(ind,ind,QVector<int>() << Qt::DisplayRole);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
EntryPoints *entryPoints;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // ENTRYPOINTMODEL_H
|
||||
|
@ -1,136 +1,136 @@
|
||||
#include "EntryPoints.h"
|
||||
#include <QDebug>
|
||||
|
||||
EntryPoints::EntryPoints(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool EntryPoints::hasEntryPointAtAddress(quint16 address)
|
||||
{
|
||||
// Assume list m_entryPoints is sorted by address (it should be)
|
||||
QListIterator<EntryPoint> it(m_entryPoints);
|
||||
while (it.hasNext())
|
||||
{
|
||||
EntryPoint ep = it.next();
|
||||
if (ep.address == address) return true;
|
||||
if (ep.address > address) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntryPoints::editPoint(int location, EntryPoint newPoint)
|
||||
{
|
||||
|
||||
if (m_entryPoints.at(location).address == newPoint.address)
|
||||
{
|
||||
m_entryPoints[location].note = newPoint.note;
|
||||
emit pointChangedAt(location);
|
||||
}
|
||||
else
|
||||
{
|
||||
removePointAt(location);
|
||||
addPoint(newPoint);
|
||||
}
|
||||
}
|
||||
|
||||
void EntryPoints::addPoint(EntryPoint ep)
|
||||
{
|
||||
if (hasEntryPointAtAddress(ep.address)) return;
|
||||
|
||||
int idx = 0;
|
||||
for (; idx < m_entryPoints.count(); idx++)
|
||||
{
|
||||
if (ep.address < m_entryPoints[idx].address)
|
||||
break;
|
||||
}
|
||||
m_entryPoints.insert(idx,ep);
|
||||
emit pointAddedAt(idx);
|
||||
emit pointAdded(ep,idx);
|
||||
}
|
||||
|
||||
void EntryPoints::removePointAt(int location)
|
||||
{
|
||||
m_entryPoints.removeAt(location);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// STREAMING OPERATORS
|
||||
|
||||
QDataStream &EntryPoints::read(QDataStream &dataStream)
|
||||
{
|
||||
quint8 version;
|
||||
dataStream >> version;
|
||||
if (version == 0)
|
||||
{
|
||||
dataStream >> m_entryPoints;
|
||||
}
|
||||
else qWarning("Unhandled version of EntryPointModel (%d) found in QDataStream",version);
|
||||
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QDataStream &EntryPoints::write(QDataStream &dataStream) const
|
||||
{
|
||||
quint8 version = 0; // Increment this and update read() if new items are added
|
||||
dataStream << version;
|
||||
dataStream << m_entryPoints;
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QList<quint16> EntryPoints::getEntryPointAddresses() const
|
||||
{
|
||||
QList<quint16> retval;
|
||||
|
||||
QListIterator<EntryPoint> it(m_entryPoints);
|
||||
while (it.hasNext())
|
||||
{
|
||||
retval.append(it.next().address);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const EntryPoints &model)
|
||||
{
|
||||
return model.write(out);
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, EntryPoints&model)
|
||||
{
|
||||
return model.read(in);
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const EntryPoint &model)
|
||||
{
|
||||
out << model.address;
|
||||
out << model.note;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, EntryPoint &model)
|
||||
{
|
||||
in >> model.address;
|
||||
in >> model.note;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// TESTING
|
||||
|
||||
void EntryPoints::doTestData()
|
||||
{
|
||||
EntryPoint ep;
|
||||
ep.address = 0x0010;
|
||||
ep.note = "Test Entry Point 1";
|
||||
addPoint(ep);
|
||||
ep.address = 0x0020;
|
||||
ep.note = "Test Entry Point 2";
|
||||
addPoint(ep);
|
||||
ep.address = 0x0030;
|
||||
ep.note = "Test Entry Point 3";
|
||||
addPoint(ep);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include "EntryPoints.h"
|
||||
#include <QDebug>
|
||||
|
||||
EntryPoints::EntryPoints(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool EntryPoints::hasEntryPointAtAddress(quint16 address)
|
||||
{
|
||||
// Assume list m_entryPoints is sorted by address (it should be)
|
||||
QListIterator<EntryPoint> it(m_entryPoints);
|
||||
while (it.hasNext())
|
||||
{
|
||||
EntryPoint ep = it.next();
|
||||
if (ep.address == address) return true;
|
||||
if (ep.address > address) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntryPoints::editPoint(int location, EntryPoint newPoint)
|
||||
{
|
||||
|
||||
if (m_entryPoints.at(location).address == newPoint.address)
|
||||
{
|
||||
m_entryPoints[location].note = newPoint.note;
|
||||
emit pointChangedAt(location);
|
||||
}
|
||||
else
|
||||
{
|
||||
removePointAt(location);
|
||||
addPoint(newPoint);
|
||||
}
|
||||
}
|
||||
|
||||
void EntryPoints::addPoint(EntryPoint ep)
|
||||
{
|
||||
if (hasEntryPointAtAddress(ep.address)) return;
|
||||
|
||||
int idx = 0;
|
||||
for (; idx < m_entryPoints.count(); idx++)
|
||||
{
|
||||
if (ep.address < m_entryPoints[idx].address)
|
||||
break;
|
||||
}
|
||||
m_entryPoints.insert(idx,ep);
|
||||
emit pointAddedAt(idx);
|
||||
emit pointAdded(ep,idx);
|
||||
}
|
||||
|
||||
void EntryPoints::removePointAt(int location)
|
||||
{
|
||||
m_entryPoints.removeAt(location);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// STREAMING OPERATORS
|
||||
|
||||
QDataStream &EntryPoints::read(QDataStream &dataStream)
|
||||
{
|
||||
quint8 version;
|
||||
dataStream >> version;
|
||||
if (version == 0)
|
||||
{
|
||||
dataStream >> m_entryPoints;
|
||||
}
|
||||
else qWarning("Unhandled version of EntryPointModel (%d) found in QDataStream",version);
|
||||
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QDataStream &EntryPoints::write(QDataStream &dataStream) const
|
||||
{
|
||||
quint8 version = 0; // Increment this and update read() if new items are added
|
||||
dataStream << version;
|
||||
dataStream << m_entryPoints;
|
||||
return dataStream;
|
||||
}
|
||||
|
||||
QList<quint16> EntryPoints::getEntryPointAddresses() const
|
||||
{
|
||||
QList<quint16> retval;
|
||||
|
||||
QListIterator<EntryPoint> it(m_entryPoints);
|
||||
while (it.hasNext())
|
||||
{
|
||||
retval.append(it.next().address);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const EntryPoints &model)
|
||||
{
|
||||
return model.write(out);
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, EntryPoints&model)
|
||||
{
|
||||
return model.read(in);
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const EntryPoint &model)
|
||||
{
|
||||
out << model.address;
|
||||
out << model.note;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, EntryPoint &model)
|
||||
{
|
||||
in >> model.address;
|
||||
in >> model.note;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// TESTING
|
||||
|
||||
void EntryPoints::doTestData()
|
||||
{
|
||||
EntryPoint ep;
|
||||
ep.address = 0x0010;
|
||||
ep.note = "Test Entry Point 1";
|
||||
addPoint(ep);
|
||||
ep.address = 0x0020;
|
||||
ep.note = "Test Entry Point 2";
|
||||
addPoint(ep);
|
||||
ep.address = 0x0030;
|
||||
ep.note = "Test Entry Point 3";
|
||||
addPoint(ep);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,52 +1,52 @@
|
||||
#ifndef ENTRYPOINTS_H
|
||||
#define ENTRYPOINTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDataStream>
|
||||
|
||||
struct EntryPoint {
|
||||
quint16 address;
|
||||
QString note;
|
||||
};
|
||||
|
||||
class EntryPoints : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EntryPoints(QObject *parent = 0);
|
||||
|
||||
bool hasEntryPointAtAddress(quint16 address);
|
||||
|
||||
const EntryPoint &at(int location) const { return m_entryPoints.at(location); }
|
||||
EntryPoint &pointRefAt(int location) { return m_entryPoints[location]; }
|
||||
EntryPoint &operator[](int location) { return m_entryPoints[location]; }
|
||||
|
||||
void editPoint(int at, EntryPoint newPoint);
|
||||
|
||||
QDataStream &read(QDataStream &dataStream);
|
||||
QDataStream &write(QDataStream &dataStream) const;
|
||||
|
||||
int numEntryPoints() const { return m_entryPoints.count(); }
|
||||
|
||||
QList<quint16> getEntryPointAddresses() const;
|
||||
|
||||
void doTestData();
|
||||
|
||||
signals:
|
||||
void pointAdded(EntryPoint &entryPoint, int location);
|
||||
void pointAddedAt(int location);
|
||||
void pointRemovedAt(int location);
|
||||
void pointChangedAt(int location);
|
||||
|
||||
public slots:
|
||||
void addPoint(EntryPoint ep);
|
||||
void removePointAt(int location);
|
||||
|
||||
protected:
|
||||
QList<EntryPoint> m_entryPoints;
|
||||
};
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const EntryPoints &model);
|
||||
QDataStream &operator>>(QDataStream &in, EntryPoints &model);
|
||||
|
||||
#endif // ENTRYPOINTS_H
|
||||
#ifndef ENTRYPOINTS_H
|
||||
#define ENTRYPOINTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDataStream>
|
||||
|
||||
struct EntryPoint {
|
||||
quint16 address;
|
||||
QString note;
|
||||
};
|
||||
|
||||
class EntryPoints : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EntryPoints(QObject *parent = 0);
|
||||
|
||||
bool hasEntryPointAtAddress(quint16 address);
|
||||
|
||||
const EntryPoint &at(int location) const { return m_entryPoints.at(location); }
|
||||
EntryPoint &pointRefAt(int location) { return m_entryPoints[location]; }
|
||||
EntryPoint &operator[](int location) { return m_entryPoints[location]; }
|
||||
|
||||
void editPoint(int at, EntryPoint newPoint);
|
||||
|
||||
QDataStream &read(QDataStream &dataStream);
|
||||
QDataStream &write(QDataStream &dataStream) const;
|
||||
|
||||
int numEntryPoints() const { return m_entryPoints.count(); }
|
||||
|
||||
QList<quint16> getEntryPointAddresses() const;
|
||||
|
||||
void doTestData();
|
||||
|
||||
signals:
|
||||
void pointAdded(EntryPoint &entryPoint, int location);
|
||||
void pointAddedAt(int location);
|
||||
void pointRemovedAt(int location);
|
||||
void pointChangedAt(int location);
|
||||
|
||||
public slots:
|
||||
void addPoint(EntryPoint ep);
|
||||
void removePointAt(int location);
|
||||
|
||||
protected:
|
||||
QList<EntryPoint> m_entryPoints;
|
||||
};
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const EntryPoints &model);
|
||||
QDataStream &operator>>(QDataStream &in, EntryPoints &model);
|
||||
|
||||
#endif // ENTRYPOINTS_H
|
||||
|
@ -1,107 +1,109 @@
|
||||
#ifndef MEMORYUSAGEMAP_H
|
||||
#define MEMORYUSAGEMAP_H
|
||||
|
||||
#include <QFlag>
|
||||
#include <QFlags>
|
||||
#include <QVector>
|
||||
|
||||
enum MemoryUsage {
|
||||
Unknown = 0x00000000,
|
||||
Data = 0x00000001,
|
||||
Operation = 0x00000002,
|
||||
// OperationArgHi = 0x00000004,
|
||||
// OperationArgLo = 0x00000008,
|
||||
OperationArg = 0x00000010,
|
||||
|
||||
RefAddressHi = 0x00000100,
|
||||
RefAddressLo = 0x00000200,
|
||||
RefAddress = RefAddressLo | RefAddressHi,
|
||||
ZeroPageRefAddress = 0x00000400,
|
||||
|
||||
InvalidOperation = 0x00001000,
|
||||
Break = 0x00002000,
|
||||
UndeterminedJump = 0x00004000,
|
||||
StopsExecution = InvalidOperation | Break | UndeterminedJump,
|
||||
|
||||
EntryPointAddr = 0x00010000,
|
||||
BranchOffsetAddr = 0x00020000,
|
||||
Jump = 0x00040000,
|
||||
Return = 0x00080000,
|
||||
};
|
||||
Q_DECLARE_FLAGS(MemoryUsages,MemoryUsage)
|
||||
|
||||
|
||||
class MemoryUsageMap : public QVector<MemoryUsages>
|
||||
{
|
||||
|
||||
public:
|
||||
MemoryUsageMap()
|
||||
{
|
||||
fill(MemoryUsage::Unknown,65536);
|
||||
}
|
||||
|
||||
void clearData()
|
||||
{
|
||||
for (int idx = 0; idx < size(); idx++)
|
||||
{
|
||||
(*this)[idx] = MemoryUsage::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void merge(const MemoryUsageMap &other)
|
||||
{
|
||||
if (other.size() != size())
|
||||
{
|
||||
qWarning("Mismatched size of MemoryMaps!");
|
||||
return;
|
||||
}
|
||||
for (int idx = 0; idx < size(); idx++)
|
||||
{
|
||||
(*this)[idx] |= other[idx];
|
||||
}
|
||||
}
|
||||
|
||||
QList<quint16> addressesWhichContain(MemoryUsage usage)
|
||||
{
|
||||
QList<quint16> retval;
|
||||
for (int idx = 0; idx < size(); idx++)
|
||||
{
|
||||
if (value(idx).testFlag(usage))
|
||||
{
|
||||
retval.append((quint16) idx);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
private:
|
||||
void clear();
|
||||
void append(const MemoryUsages &);
|
||||
void append(MemoryUsages &&);
|
||||
void append(const QVector<MemoryUsages>);
|
||||
void insert(int,const MemoryUsages &);
|
||||
void insert(int,int,const MemoryUsages &);
|
||||
void move(int,int);
|
||||
void prepend(const MemoryUsages&);
|
||||
void push_back(const MemoryUsages&);
|
||||
void push_back(MemoryUsages&&);
|
||||
void push_front(const MemoryUsages&);
|
||||
void remove(int);
|
||||
void remove(int,int);
|
||||
void removeAll(const MemoryUsages&);
|
||||
void removeAt(int);
|
||||
void removeFirst();
|
||||
void removeLast();
|
||||
bool removeOne(const MemoryUsages&);
|
||||
void reserve(int);
|
||||
void resize(int);
|
||||
void swap(QVector<MemoryUsages>&);
|
||||
MemoryUsages &takeAt(int);
|
||||
MemoryUsages &takeFirst();
|
||||
MemoryUsages &takeLast();
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(MemoryUsages)
|
||||
|
||||
#endif // MEMORYUSAGEMAP_H
|
||||
#ifndef MEMORYUSAGEMAP_H
|
||||
#define MEMORYUSAGEMAP_H
|
||||
|
||||
#include <QFlag>
|
||||
#include <QFlags>
|
||||
#include <QVector>
|
||||
#include <QList>
|
||||
|
||||
|
||||
enum MemoryUsage {
|
||||
Unknown = 0x00000000,
|
||||
Data = 0x00000001,
|
||||
Operation = 0x00000002,
|
||||
// OperationArgHi = 0x00000004,
|
||||
// OperationArgLo = 0x00000008,
|
||||
OperationArg = 0x00000010,
|
||||
|
||||
RefAddressHi = 0x00000100,
|
||||
RefAddressLo = 0x00000200,
|
||||
RefAddress = RefAddressLo | RefAddressHi,
|
||||
ZeroPageRefAddress = 0x00000400,
|
||||
|
||||
InvalidOperation = 0x00001000,
|
||||
Break = 0x00002000,
|
||||
UndeterminedJump = 0x00004000,
|
||||
StopsExecution = InvalidOperation | Break | UndeterminedJump,
|
||||
|
||||
EntryPointAddr = 0x00010000,
|
||||
BranchOffsetAddr = 0x00020000,
|
||||
Jump = 0x00040000,
|
||||
Return = 0x00080000,
|
||||
};
|
||||
Q_DECLARE_FLAGS(MemoryUsages,MemoryUsage)
|
||||
|
||||
|
||||
class MemoryUsageMap : public QVector<MemoryUsages>
|
||||
{
|
||||
|
||||
public:
|
||||
MemoryUsageMap()
|
||||
{
|
||||
fill(MemoryUsage::Unknown,65536);
|
||||
}
|
||||
|
||||
void clearData()
|
||||
{
|
||||
for (int idx = 0; idx < size(); idx++)
|
||||
{
|
||||
(*this)[idx] = MemoryUsage::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void merge(const MemoryUsageMap &other)
|
||||
{
|
||||
if (other.size() != size())
|
||||
{
|
||||
qWarning("Mismatched size of MemoryMaps!");
|
||||
return;
|
||||
}
|
||||
for (int idx = 0; idx < size(); idx++)
|
||||
{
|
||||
(*this)[idx] |= other[idx];
|
||||
}
|
||||
}
|
||||
|
||||
QList<quint16> addressesWhichContain(MemoryUsage usage)
|
||||
{
|
||||
QList<quint16> retval;
|
||||
for (int idx = 0; idx < size(); idx++)
|
||||
{
|
||||
if (value(idx).testFlag(usage))
|
||||
{
|
||||
retval.append((quint16) idx);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
private:
|
||||
void clear();
|
||||
void append(const MemoryUsages &);
|
||||
void append(MemoryUsages &&);
|
||||
void append(const QVector<MemoryUsages>);
|
||||
void insert(int,const MemoryUsages &);
|
||||
void insert(int,int,const MemoryUsages &);
|
||||
void move(int,int);
|
||||
void prepend(const MemoryUsages&);
|
||||
void push_back(const MemoryUsages&);
|
||||
void push_back(MemoryUsages&&);
|
||||
void push_front(const MemoryUsages&);
|
||||
void remove(int);
|
||||
void remove(int,int);
|
||||
void removeAll(const MemoryUsages&);
|
||||
void removeAt(int);
|
||||
void removeFirst();
|
||||
void removeLast();
|
||||
bool removeOne(const MemoryUsages&);
|
||||
void reserve(int);
|
||||
void resize(int);
|
||||
void swap(QVector<MemoryUsages>&);
|
||||
MemoryUsages &takeAt(int);
|
||||
MemoryUsages &takeFirst();
|
||||
MemoryUsages &takeLast();
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(MemoryUsages)
|
||||
|
||||
#endif // MEMORYUSAGEMAP_H
|
||||
|
@ -1,31 +1,31 @@
|
||||
#include <QDebug>
|
||||
#include "binaryfile.h"
|
||||
#include "util.h"
|
||||
|
||||
BinaryFile::BinaryFile(QByteArray data) : GenericFile(data)
|
||||
{
|
||||
m_length = 0;
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryFile::setData(QByteArray data)
|
||||
{
|
||||
if (data.length() >= 4) {
|
||||
QByteArray metadata = data.left(4);
|
||||
m_data = data.mid(4);
|
||||
setAddress(makeWord(metadata[0],metadata[1]));
|
||||
m_length = makeWord(metadata[2],metadata[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryFile::dump()
|
||||
{
|
||||
qDebug() << QString("Address: %1 Length: %2")
|
||||
.arg((quint16) address(),4,16,QChar('0'))
|
||||
.arg(m_length,4,16,QChar('0')).toUpper();
|
||||
qDebug() << QString("Data Length Recorded: %1")
|
||||
.arg(m_data.length(),4,16,QChar('0')).toUpper();
|
||||
}
|
||||
#include <QDebug>
|
||||
#include "binaryfile.h"
|
||||
#include "util.h"
|
||||
|
||||
BinaryFile::BinaryFile(QByteArray data) : GenericFile(data)
|
||||
{
|
||||
m_length = 0;
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryFile::setData(QByteArray data)
|
||||
{
|
||||
if (data.length() >= 4) {
|
||||
QByteArray metadata = data.left(4);
|
||||
m_data = data.mid(4);
|
||||
setAddress(makeWord(metadata[0],metadata[1]));
|
||||
m_length = makeWord(metadata[2],metadata[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryFile::dump()
|
||||
{
|
||||
qDebug() << QString("Address: %1 Length: %2")
|
||||
.arg((quint16) address(),4,16,QChar('0'))
|
||||
.arg(m_length,4,16,QChar('0')).toUpper();
|
||||
qDebug() << QString("Data Length Recorded: %1")
|
||||
.arg(m_data.length(),4,16,QChar('0')).toUpper();
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
#ifndef BINARYFILE_H
|
||||
#define BINARYFILE_H
|
||||
|
||||
#include "genericfile.h"
|
||||
|
||||
class BinaryFile : public GenericFile
|
||||
{
|
||||
public:
|
||||
BinaryFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
|
||||
virtual quint16 length() { return m_length; }
|
||||
|
||||
void dump();
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // BINARYFILE_H
|
||||
#ifndef BINARYFILE_H
|
||||
#define BINARYFILE_H
|
||||
|
||||
#include "genericfile.h"
|
||||
|
||||
class BinaryFile : public GenericFile
|
||||
{
|
||||
public:
|
||||
BinaryFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
|
||||
virtual quint16 length() { return m_length; }
|
||||
|
||||
void dump();
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // BINARYFILE_H
|
||||
|
@ -1,68 +1,68 @@
|
||||
#include "binaryfilemetadata.h"
|
||||
#include "genericfile.h"
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
BinaryFileMetadata::BinaryFileMetadata(GenericFile *file, quint16 defaultAddress, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_file = file;
|
||||
m_defaultAddress = defaultAddress;
|
||||
|
||||
m_eps = new EntryPoints(this);
|
||||
m_as = new AssemblerSymbols(this);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
void BinaryFileMetadata::load()
|
||||
{
|
||||
QFile infile(QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm"));
|
||||
if (infile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qDebug() << "Loading binary file metadata from" << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm");
|
||||
QDataStream ds(&infile);
|
||||
ds >> *m_eps;
|
||||
ds >> *m_as;
|
||||
infile.close();
|
||||
}
|
||||
else qDebug() << "Cannot open " << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm") << "for reading";
|
||||
|
||||
}
|
||||
|
||||
void BinaryFileMetadata::save()
|
||||
{
|
||||
QFile outfile(QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm"));
|
||||
if (outfile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
qDebug() << "Saving binary file metadata to" << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm");
|
||||
QDataStream ds(&outfile);
|
||||
ds << *m_eps;
|
||||
ds << *m_as;
|
||||
outfile.close();
|
||||
}
|
||||
else qDebug() << "Cannot open " << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm") << "for writing";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "binaryfilemetadata.h"
|
||||
#include "genericfile.h"
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
BinaryFileMetadata::BinaryFileMetadata(GenericFile *file, quint16 defaultAddress, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_file = file;
|
||||
m_defaultAddress = defaultAddress;
|
||||
|
||||
m_eps = new EntryPoints(this);
|
||||
m_as = new AssemblerSymbols(this);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
void BinaryFileMetadata::load()
|
||||
{
|
||||
QFile infile(QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm"));
|
||||
if (infile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qDebug() << "Loading binary file metadata from" << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm");
|
||||
QDataStream ds(&infile);
|
||||
ds >> *m_eps;
|
||||
ds >> *m_as;
|
||||
infile.close();
|
||||
}
|
||||
else qDebug() << "Cannot open " << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm") << "for reading";
|
||||
|
||||
}
|
||||
|
||||
void BinaryFileMetadata::save()
|
||||
{
|
||||
QFile outfile(QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm"));
|
||||
if (outfile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
qDebug() << "Saving binary file metadata to" << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm");
|
||||
QDataStream ds(&outfile);
|
||||
ds << *m_eps;
|
||||
ds << *m_as;
|
||||
outfile.close();
|
||||
}
|
||||
else qDebug() << "Cannot open " << QString("%1%2%3")
|
||||
.arg(m_file->diskFile()->getMetaDataPath())
|
||||
.arg(m_file->filename())
|
||||
.arg(".bfm") << "for writing";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,47 +1,47 @@
|
||||
#ifndef BINARYFILEMETADATA_H
|
||||
#define BINARYFILEMETADATA_H
|
||||
|
||||
#include "EntryPoints.h"
|
||||
#include "AssemblerSymbols.h"
|
||||
#include "genericfile.h"
|
||||
#include "binaryfile.h"
|
||||
|
||||
#include <Qt>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
|
||||
|
||||
|
||||
|
||||
class BinaryFileMetadata : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BinaryFileMetadata(GenericFile *file, quint16 defaultAddress, QObject *parent = 0);
|
||||
|
||||
QString filename() const { return m_file->filename(); }
|
||||
|
||||
EntryPoints *entryPoints() { return m_eps; }
|
||||
AssemblerSymbols *assemblerSymbols() { return m_as; }
|
||||
|
||||
signals:
|
||||
void doDisassemble(QList<quint16>);
|
||||
|
||||
public slots:
|
||||
void load();
|
||||
void save();
|
||||
|
||||
void requestDisassembly() { emit doDisassemble(m_eps->getEntryPointAddresses()); }
|
||||
|
||||
private:
|
||||
|
||||
EntryPoints *m_eps;
|
||||
AssemblerSymbols *m_as;
|
||||
|
||||
GenericFile *m_file;
|
||||
|
||||
quint16 m_defaultAddress;
|
||||
};
|
||||
|
||||
#endif // BINARYFILEMETADATA_H
|
||||
#ifndef BINARYFILEMETADATA_H
|
||||
#define BINARYFILEMETADATA_H
|
||||
|
||||
#include "EntryPoints.h"
|
||||
#include "AssemblerSymbols.h"
|
||||
#include "genericfile.h"
|
||||
#include "binaryfile.h"
|
||||
|
||||
#include <Qt>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
|
||||
|
||||
|
||||
|
||||
class BinaryFileMetadata : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BinaryFileMetadata(GenericFile *file, quint16 defaultAddress, QObject *parent = 0);
|
||||
|
||||
QString filename() const { return m_file->filename(); }
|
||||
|
||||
EntryPoints *entryPoints() { return m_eps; }
|
||||
AssemblerSymbols *assemblerSymbols() { return m_as; }
|
||||
|
||||
signals:
|
||||
void doDisassemble(QList<quint16>);
|
||||
|
||||
public slots:
|
||||
void load();
|
||||
void save();
|
||||
|
||||
void requestDisassembly() { emit doDisassemble(m_eps->getEntryPointAddresses()); }
|
||||
|
||||
private:
|
||||
|
||||
EntryPoints *m_eps;
|
||||
AssemblerSymbols *m_as;
|
||||
|
||||
GenericFile *m_file;
|
||||
|
||||
quint16 m_defaultAddress;
|
||||
};
|
||||
|
||||
#endif // BINARYFILEMETADATA_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,215 +1,215 @@
|
||||
#ifndef DISASSEMBLER_H
|
||||
#define DISASSEMBLER_H
|
||||
|
||||
#include "MemoryUsageMap.h"
|
||||
#include "util.h"
|
||||
#include "JumpLineManager.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
#include <QDebug>
|
||||
#include <QStack>
|
||||
|
||||
|
||||
enum AddressMode {
|
||||
AM_InvalidOp,
|
||||
AM_Absolute, // a
|
||||
AM_AbsoluteIndexedIndirect, // (a,x)
|
||||
AM_AbsoluteIndexedWithX, // a,x
|
||||
AM_AbsoluteIndexedWithY, // a,y
|
||||
AM_AbsoluteIndirect, // (a)
|
||||
AM_Immediate, // #
|
||||
AM_Implied, // i
|
||||
AM_Accumulator, // A
|
||||
AM_ProgramCounterRelative, // r
|
||||
AM_ZeroPage, // zp
|
||||
AM_ZeroPageIndexedIndirect, // (zp,x)
|
||||
AM_ZeroPageIndexedWithX, // zp,x
|
||||
AM_ZeroPageIndexedWithY, // zp,y
|
||||
AM_ZeroPageIndirect, // (zp)
|
||||
AM_ZeroPageIndirectIndexedWithY // (zp),y
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AddressStack
|
||||
{
|
||||
public:
|
||||
AddressStack() { }
|
||||
|
||||
bool push(quint16 address, bool force = false) {
|
||||
if (force || (!m_stack.contains(address)))
|
||||
{
|
||||
qDebug() << " PUSH: " << uint16ToHex(address);
|
||||
m_stack.push(address);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isEmpty() { return m_stack.isEmpty(); }
|
||||
quint16 pop() { return m_stack.pop(); }
|
||||
|
||||
private:
|
||||
QStack<quint16> m_stack;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct AssyInstruction {
|
||||
|
||||
public:
|
||||
|
||||
AssyInstruction(quint8 opcode = 0x00, QString mnemonic = "???", AddressMode am = AM_InvalidOp);
|
||||
|
||||
AddressMode addressMode() { return m_addressMode; }
|
||||
|
||||
QString mnemonic() { return m_mnemonic; }
|
||||
|
||||
quint8 opcode() { return m_opcode; }
|
||||
|
||||
quint8 numArgs();
|
||||
|
||||
QString debugStr() { return QString("%1 %2 %3").arg(uint8ToHex(m_opcode)).arg(m_mnemonic).arg(m_addressMode); }
|
||||
|
||||
private:
|
||||
QString m_mnemonic;
|
||||
quint8 m_opcode;
|
||||
AddressMode m_addressMode;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DisassembledItem {
|
||||
public:
|
||||
DisassembledItem() { init(); }
|
||||
|
||||
DisassembledItem(AssyInstruction instr);
|
||||
|
||||
bool operator<(const DisassembledItem &other) const { return (address() < other.address()); }
|
||||
|
||||
void setInstruction(AssyInstruction instr);
|
||||
|
||||
void setAddress(quint16 add) { m_address = add; }
|
||||
void setDisassembledString(QString ds) { m_disassembly_text = ds; }
|
||||
void setHexValues(QByteArray hv) { m_hexvalues = hv; }
|
||||
void setHexString(QString hs) { m_hexstring = hs; }
|
||||
void setBranch(bool branch) { m_is_branch = branch; }
|
||||
void setJump(bool jump) { m_is_jump = jump; }
|
||||
void setJsr(bool jsr) { m_is_jsr = jsr; }
|
||||
void setTargetAddress(quint16 ta) { m_unknown_ta = false; m_target_address = ta; }
|
||||
void setRawArgument(quint16 arg) { m_has_arg = true; m_raw_arg = arg; }
|
||||
void setCanNotFollow(bool canNotFollow) { m_canNotFollow = canNotFollow; }
|
||||
void setIsInvalidOp(bool isInvalid) { m_isInvalidOp = isInvalid; }
|
||||
|
||||
AssyInstruction assyInstruction() const { return m_instruction; }
|
||||
QString rawDisassembledString() const { return m_disassembly_text; }
|
||||
QString disassembledString();
|
||||
quint16 address() const { return m_address; }
|
||||
QString hexAddress() const { return QString("%1").arg(m_address,4,16,QChar('0')).toUpper(); }
|
||||
QByteArray hexValues() const { return m_hexvalues; }
|
||||
QString hexString() const { return m_hexstring; }
|
||||
bool isBranch() const { return m_is_branch; }
|
||||
bool isJump() const { return m_is_jump; }
|
||||
bool isJsr() const { return m_is_jsr; }
|
||||
bool isReturn() { return (m_instruction.opcode() == 0x60) || m_instruction.opcode() == 0x40; }
|
||||
bool isBreak() { return (m_instruction.opcode() == 0x00); }
|
||||
bool isInvalidOp() { return m_isInvalidOp; }
|
||||
|
||||
bool canNotFollow() { return m_canNotFollow; }
|
||||
|
||||
bool stopsProcessing() {
|
||||
if (isReturn()) qDebug() << "Is Return";
|
||||
if (isInvalidOp()) qDebug() << "Is Invalid Op" << uint8ToHex(m_instruction.opcode());
|
||||
if (canNotFollow()) qDebug() << "Not following jump";
|
||||
if (isBreak()) qDebug() << "Is Break";
|
||||
return isBreak() || isInvalidOp() || isReturn() || canNotFollow(); }
|
||||
|
||||
quint16 nextContiguousAddress() { return m_nextContiguousAddress; }
|
||||
quint16 nextFlowAddress() { return m_nextFlowAddress; }
|
||||
|
||||
void setNextContiguousAddress(quint16 addr) { m_nextContiguousAddress = addr; }
|
||||
void setNextFlowAddress(quint16 addr) { m_nextFlowAddress = addr; }
|
||||
|
||||
quint16 targetAddress() const { return m_target_address; }
|
||||
bool hasArg() const { return m_has_arg; }
|
||||
quint16 arg16() { return m_raw_arg; }
|
||||
quint8 arg8() { return m_raw_arg % 256; }
|
||||
QString arg16Str() { return QString("%1").arg(arg16(),4,16,QChar('0')).toUpper(); }
|
||||
QString arg8Str() { return QString("%1").arg(arg8(),2,16,QChar('0')).toUpper(); }
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
quint16 m_address;
|
||||
quint16 m_nextContiguousAddress;
|
||||
quint16 m_nextFlowAddress;
|
||||
quint16 m_target_address;
|
||||
|
||||
QByteArray m_hexvalues;
|
||||
QString m_disassembly_text;
|
||||
QString m_hexstring;
|
||||
bool m_is_branch;
|
||||
bool m_is_jump;
|
||||
bool m_is_jsr;
|
||||
AssyInstruction m_instruction;
|
||||
bool m_unknown_ta;
|
||||
quint16 m_raw_arg;
|
||||
bool m_has_arg;
|
||||
bool m_isInvalidOp;
|
||||
bool m_canNotFollow;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Disassembler
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
Disassembler(QByteArray memimage);
|
||||
|
||||
enum ProcessorType {
|
||||
P6502,
|
||||
P65C02
|
||||
};
|
||||
|
||||
QList<DisassembledItem> disassemble(quint16 from,
|
||||
quint16 to,
|
||||
QList<quint16> entryPoints,
|
||||
bool processRecursively = true);
|
||||
|
||||
MemoryUsageMap *memoryUsageMap() { return &m_memusagemap; }
|
||||
|
||||
void setUnknownToData(quint16 from, quint16 to);
|
||||
|
||||
QString getMnemonicForOp(quint8 opcode)
|
||||
{
|
||||
return m_opcodeinfo[opcode].mnemonic();
|
||||
}
|
||||
|
||||
JumpLines getJumpLines() const { return m_jumplines; }
|
||||
|
||||
private:
|
||||
bool disassembleOp(quint16 address, DisassembledItem &retval, MemoryUsageMap *memuse = Q_NULLPTR);
|
||||
void makeOpcodeTable();
|
||||
|
||||
|
||||
quint16 m_from;
|
||||
quint16 m_to;
|
||||
|
||||
QHash<quint8,AssyInstruction> m_opcodeinfo;
|
||||
QByteArray m_memimage;
|
||||
|
||||
AddressStack m_stack;
|
||||
|
||||
MemoryUsageMap m_memusagemap;
|
||||
|
||||
JumpLineManager m_jlm;
|
||||
|
||||
JumpLines m_jumplines;
|
||||
|
||||
};
|
||||
|
||||
#endif // DISASSEMBLER_H
|
||||
#ifndef DISASSEMBLER_H
|
||||
#define DISASSEMBLER_H
|
||||
|
||||
#include "MemoryUsageMap.h"
|
||||
#include "util.h"
|
||||
#include "JumpLineManager.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
#include <QDebug>
|
||||
#include <QStack>
|
||||
|
||||
|
||||
enum AddressMode {
|
||||
AM_InvalidOp,
|
||||
AM_Absolute, // a
|
||||
AM_AbsoluteIndexedIndirect, // (a,x)
|
||||
AM_AbsoluteIndexedWithX, // a,x
|
||||
AM_AbsoluteIndexedWithY, // a,y
|
||||
AM_AbsoluteIndirect, // (a)
|
||||
AM_Immediate, // #
|
||||
AM_Implied, // i
|
||||
AM_Accumulator, // A
|
||||
AM_ProgramCounterRelative, // r
|
||||
AM_ZeroPage, // zp
|
||||
AM_ZeroPageIndexedIndirect, // (zp,x)
|
||||
AM_ZeroPageIndexedWithX, // zp,x
|
||||
AM_ZeroPageIndexedWithY, // zp,y
|
||||
AM_ZeroPageIndirect, // (zp)
|
||||
AM_ZeroPageIndirectIndexedWithY // (zp),y
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AddressStack
|
||||
{
|
||||
public:
|
||||
AddressStack() { }
|
||||
|
||||
bool push(quint16 address, bool force = false) {
|
||||
if (force || (!m_stack.contains(address)))
|
||||
{
|
||||
qDebug() << " PUSH: " << uint16ToHex(address);
|
||||
m_stack.push(address);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isEmpty() { return m_stack.isEmpty(); }
|
||||
quint16 pop() { return m_stack.pop(); }
|
||||
|
||||
private:
|
||||
QStack<quint16> m_stack;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct AssyInstruction {
|
||||
|
||||
public:
|
||||
|
||||
AssyInstruction(quint8 opcode = 0x00, QString mnemonic = "???", AddressMode am = AM_InvalidOp);
|
||||
|
||||
AddressMode addressMode() { return m_addressMode; }
|
||||
|
||||
QString mnemonic() { return m_mnemonic; }
|
||||
|
||||
quint8 opcode() { return m_opcode; }
|
||||
|
||||
quint8 numArgs();
|
||||
|
||||
QString debugStr() { return QString("%1 %2 %3").arg(uint8ToHex(m_opcode)).arg(m_mnemonic).arg(m_addressMode); }
|
||||
|
||||
private:
|
||||
QString m_mnemonic;
|
||||
quint8 m_opcode;
|
||||
AddressMode m_addressMode;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DisassembledItem {
|
||||
public:
|
||||
DisassembledItem() { init(); }
|
||||
|
||||
DisassembledItem(AssyInstruction instr);
|
||||
|
||||
bool operator<(const DisassembledItem &other) const { return (address() < other.address()); }
|
||||
|
||||
void setInstruction(AssyInstruction instr);
|
||||
|
||||
void setAddress(quint16 add) { m_address = add; }
|
||||
void setDisassembledString(QString ds) { m_disassembly_text = ds; }
|
||||
void setHexValues(QByteArray hv) { m_hexvalues = hv; }
|
||||
void setHexString(QString hs) { m_hexstring = hs; }
|
||||
void setBranch(bool branch) { m_is_branch = branch; }
|
||||
void setJump(bool jump) { m_is_jump = jump; }
|
||||
void setJsr(bool jsr) { m_is_jsr = jsr; }
|
||||
void setTargetAddress(quint16 ta) { m_unknown_ta = false; m_target_address = ta; }
|
||||
void setRawArgument(quint16 arg) { m_has_arg = true; m_raw_arg = arg; }
|
||||
void setCanNotFollow(bool canNotFollow) { m_canNotFollow = canNotFollow; }
|
||||
void setIsInvalidOp(bool isInvalid) { m_isInvalidOp = isInvalid; }
|
||||
|
||||
AssyInstruction assyInstruction() const { return m_instruction; }
|
||||
QString rawDisassembledString() const { return m_disassembly_text; }
|
||||
QString disassembledString();
|
||||
quint16 address() const { return m_address; }
|
||||
QString hexAddress() const { return QString("%1").arg(m_address,4,16,QChar('0')).toUpper(); }
|
||||
QByteArray hexValues() const { return m_hexvalues; }
|
||||
QString hexString() const { return m_hexstring; }
|
||||
bool isBranch() const { return m_is_branch; }
|
||||
bool isJump() const { return m_is_jump; }
|
||||
bool isJsr() const { return m_is_jsr; }
|
||||
bool isReturn() { return (m_instruction.opcode() == 0x60) || m_instruction.opcode() == 0x40; }
|
||||
bool isBreak() { return (m_instruction.opcode() == 0x00); }
|
||||
bool isInvalidOp() { return m_isInvalidOp; }
|
||||
|
||||
bool canNotFollow() { return m_canNotFollow; }
|
||||
|
||||
bool stopsProcessing() {
|
||||
if (isReturn()) qDebug() << "Is Return";
|
||||
if (isInvalidOp()) qDebug() << "Is Invalid Op" << uint8ToHex(m_instruction.opcode());
|
||||
if (canNotFollow()) qDebug() << "Not following jump";
|
||||
if (isBreak()) qDebug() << "Is Break";
|
||||
return isBreak() || isInvalidOp() || isReturn() || canNotFollow(); }
|
||||
|
||||
quint16 nextContiguousAddress() { return m_nextContiguousAddress; }
|
||||
quint16 nextFlowAddress() { return m_nextFlowAddress; }
|
||||
|
||||
void setNextContiguousAddress(quint16 addr) { m_nextContiguousAddress = addr; }
|
||||
void setNextFlowAddress(quint16 addr) { m_nextFlowAddress = addr; }
|
||||
|
||||
quint16 targetAddress() const { return m_target_address; }
|
||||
bool hasArg() const { return m_has_arg; }
|
||||
quint16 arg16() { return m_raw_arg; }
|
||||
quint8 arg8() { return m_raw_arg % 256; }
|
||||
QString arg16Str() { return QString("%1").arg(arg16(),4,16,QChar('0')).toUpper(); }
|
||||
QString arg8Str() { return QString("%1").arg(arg8(),2,16,QChar('0')).toUpper(); }
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
quint16 m_address;
|
||||
quint16 m_nextContiguousAddress;
|
||||
quint16 m_nextFlowAddress;
|
||||
quint16 m_target_address;
|
||||
|
||||
QByteArray m_hexvalues;
|
||||
QString m_disassembly_text;
|
||||
QString m_hexstring;
|
||||
bool m_is_branch;
|
||||
bool m_is_jump;
|
||||
bool m_is_jsr;
|
||||
AssyInstruction m_instruction;
|
||||
bool m_unknown_ta;
|
||||
quint16 m_raw_arg;
|
||||
bool m_has_arg;
|
||||
bool m_isInvalidOp;
|
||||
bool m_canNotFollow;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Disassembler
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
Disassembler(QByteArray memimage);
|
||||
|
||||
enum ProcessorType {
|
||||
P6502,
|
||||
P65C02
|
||||
};
|
||||
|
||||
QList<DisassembledItem> disassemble(quint16 from,
|
||||
quint16 to,
|
||||
QList<quint16> entryPoints,
|
||||
bool processRecursively = true);
|
||||
|
||||
MemoryUsageMap *memoryUsageMap() { return &m_memusagemap; }
|
||||
|
||||
void setUnknownToData(quint16 from, quint16 to);
|
||||
|
||||
QString getMnemonicForOp(quint8 opcode)
|
||||
{
|
||||
return m_opcodeinfo[opcode].mnemonic();
|
||||
}
|
||||
|
||||
JumpLines getJumpLines() const { return m_jumplines; }
|
||||
|
||||
private:
|
||||
bool disassembleOp(quint16 address, DisassembledItem &retval, MemoryUsageMap *memuse = Q_NULLPTR);
|
||||
void makeOpcodeTable();
|
||||
|
||||
|
||||
quint16 m_from;
|
||||
quint16 m_to;
|
||||
|
||||
QHash<quint8,AssyInstruction> m_opcodeinfo;
|
||||
QByteArray m_memimage;
|
||||
|
||||
AddressStack m_stack;
|
||||
|
||||
MemoryUsageMap m_memusagemap;
|
||||
|
||||
JumpLineManager m_jlm;
|
||||
|
||||
JumpLines m_jumplines;
|
||||
|
||||
};
|
||||
|
||||
#endif // DISASSEMBLER_H
|
||||
|
@ -1,53 +1,56 @@
|
||||
#include "catalogsector.h"
|
||||
#include "sector.h"
|
||||
|
||||
CatalogSector::CatalogSector(Sector *data)
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
m_next.track = m_data->rawData()[0x01];
|
||||
m_next.sector = m_data->rawData()[0x02];
|
||||
|
||||
for (int idx = 0; idx<7; idx++)
|
||||
{
|
||||
FileDescriptiveEntry fde = makeFDE(idx*0x23+0x0B);
|
||||
if (fde.firstTSListSector != TSPair(0,0)) {
|
||||
m_fdes.append(fde);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CatalogSector::dumpFDEs() {
|
||||
for (int idx = 0; idx<7; idx++)
|
||||
{
|
||||
FileDescriptiveEntry fde = m_fdes[idx];
|
||||
if (fde.firstTSListSector != TSPair(0,0)) {
|
||||
qDebug() << "FDE #"<<idx;
|
||||
fde.dump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
||||
{
|
||||
FileDescriptiveEntry fde;
|
||||
fde.firstTSListSector.track = m_data->rawData()[offset + 0x00];
|
||||
fde.firstTSListSector.sector = m_data->rawData()[offset + 0x01];
|
||||
fde.fileTypeAndFlags = m_data->rawData()[offset + 0x02];
|
||||
fde.lengthInSectors = makeWord( m_data->rawData()[offset + 0x21], m_data->rawData()[offset + 0x22]);
|
||||
for (int idx = 0x03; idx <= 0x20; idx++) {
|
||||
fde.filename.append(m_data->rawData()[idx+offset]);
|
||||
}
|
||||
if (fde.firstTSListSector.track == 0xFF)
|
||||
{
|
||||
//TODO: Double check this stuff. applevision.dsk is a good example.
|
||||
qDebug() << "File" << fde.filename.printable() << "is deleted";
|
||||
fde.deleted = true;
|
||||
qDebug() << fde.filename;
|
||||
fde.firstTSListSector.track = m_data->rawData()[offset + 0x20];
|
||||
qDebug() << " New track: " << (quint8) fde.firstTSListSector.track;
|
||||
qDebug() << " Sector: " << fde.firstTSListSector.sector;
|
||||
|
||||
}
|
||||
return fde;
|
||||
}
|
||||
#include "catalogsector.h"
|
||||
#include "sector.h"
|
||||
|
||||
CatalogSector::CatalogSector(Sector *data)
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
m_next.track = m_data->rawData()[0x01];
|
||||
m_next.sector = m_data->rawData()[0x02];
|
||||
|
||||
for (int idx = 0; idx<7; idx++)
|
||||
{
|
||||
FileDescriptiveEntry fde = makeFDE(idx*0x23+0x0B);
|
||||
if (fde.firstTSListSector != TSPair(0,0)) {
|
||||
m_fdes.append(fde);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CatalogSector::dumpFDEs() {
|
||||
for (int idx = 0; idx<7; idx++)
|
||||
{
|
||||
FileDescriptiveEntry fde = m_fdes[idx];
|
||||
if (fde.firstTSListSector != TSPair(0,0)) {
|
||||
qDebug() << "FDE #"<<idx;
|
||||
fde.dump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
||||
{
|
||||
FileDescriptiveEntry fde;
|
||||
fde.firstTSListSector.track = m_data->rawData()[offset + 0x00];
|
||||
fde.firstTSListSector.sector = m_data->rawData()[offset + 0x01];
|
||||
fde.fileTypeAndFlags = m_data->rawData()[offset + 0x02];
|
||||
fde.lengthInSectors = makeWord( m_data->rawData()[offset + 0x21],
|
||||
m_data->rawData()[offset + 0x22]);
|
||||
|
||||
for (int idx = 0x03; idx <= 0x20; idx++) {
|
||||
fde.filename.append(m_data->rawData()[idx+offset]);
|
||||
}
|
||||
|
||||
if (fde.firstTSListSector.track == 0xFF)
|
||||
{
|
||||
//TODO: Double check this stuff. applevision.dsk is a good example.
|
||||
qDebug() << "File" << fde.filename.printable() << "is deleted";
|
||||
fde.deleted = true;
|
||||
qDebug() << fde.filename;
|
||||
fde.firstTSListSector.track = m_data->rawData()[offset + 0x20];
|
||||
qDebug() << " New track: " << (quint8) fde.firstTSListSector.track;
|
||||
qDebug() << " Sector: " << fde.firstTSListSector.sector;
|
||||
}
|
||||
|
||||
return fde;
|
||||
}
|
||||
|
@ -1,45 +1,45 @@
|
||||
#ifndef CATALOGSECTOR_H
|
||||
#define CATALOGSECTOR_H
|
||||
|
||||
#include <Qt>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
|
||||
#include "util.h"
|
||||
#include "applestring.h"
|
||||
#include "filedescriptiveentry.h"
|
||||
|
||||
class Sector;
|
||||
|
||||
|
||||
|
||||
class CatalogSector
|
||||
{
|
||||
public:
|
||||
CatalogSector(Sector *sector);
|
||||
|
||||
FileDescriptiveEntry &getFDE(quint8 number) {
|
||||
if (number >= m_fdes.length()) {
|
||||
number = m_fdes.length() - 1;
|
||||
}
|
||||
return m_fdes[number];
|
||||
}
|
||||
|
||||
QList<FileDescriptiveEntry> getFDEs() { return m_fdes; }
|
||||
|
||||
TSPair nextCatalogSector() { return m_next; }
|
||||
|
||||
void dumpFDEs();
|
||||
|
||||
Sector *getSector() const { return m_data; }
|
||||
|
||||
private:
|
||||
FileDescriptiveEntry makeFDE(int offset);
|
||||
|
||||
private:
|
||||
Sector *m_data;
|
||||
QList<FileDescriptiveEntry> m_fdes;
|
||||
TSPair m_next;
|
||||
};
|
||||
|
||||
#endif // CATALOGSECTOR_H
|
||||
#ifndef CATALOGSECTOR_H
|
||||
#define CATALOGSECTOR_H
|
||||
|
||||
#include <Qt>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
|
||||
#include "util.h"
|
||||
#include "applestring.h"
|
||||
#include "filedescriptiveentry.h"
|
||||
|
||||
class Sector;
|
||||
|
||||
|
||||
|
||||
class CatalogSector
|
||||
{
|
||||
public:
|
||||
CatalogSector(Sector *sector);
|
||||
|
||||
FileDescriptiveEntry &getFDE(quint8 number) {
|
||||
if (number >= m_fdes.length()) {
|
||||
number = m_fdes.length() - 1;
|
||||
}
|
||||
return m_fdes[number];
|
||||
}
|
||||
|
||||
QList<FileDescriptiveEntry> getFDEs() { return m_fdes; }
|
||||
|
||||
TSPair nextCatalogSector() { return m_next; }
|
||||
|
||||
void dumpFDEs();
|
||||
|
||||
Sector *getSector() const { return m_data; }
|
||||
|
||||
private:
|
||||
FileDescriptiveEntry makeFDE(int offset);
|
||||
|
||||
private:
|
||||
Sector *m_data;
|
||||
QList<FileDescriptiveEntry> m_fdes;
|
||||
TSPair m_next;
|
||||
};
|
||||
|
||||
#endif // CATALOGSECTOR_H
|
||||
|
@ -1,181 +1,186 @@
|
||||
#include "diskfile.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
||||
#include "tracksectorlist.h"
|
||||
#include "applesoftfile.h"
|
||||
#include "binaryfile.h"
|
||||
#include "relocatablefile.h"
|
||||
#include "textfile.h"
|
||||
|
||||
DiskFile::DiskFile(QString filename)
|
||||
{
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
read(filename);
|
||||
}
|
||||
}
|
||||
|
||||
DiskFile::~DiskFile()
|
||||
{
|
||||
foreach (GenericFile *file, m_files)
|
||||
{
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskFile::read(QString filename)
|
||||
{
|
||||
m_fullImageName = filename;
|
||||
m_imageName = QFileInfo(filename).fileName();
|
||||
if (m_imageName.toUpper().contains(".D13"))
|
||||
{
|
||||
m_sectors_per_track = 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sectors_per_track = 16;
|
||||
}
|
||||
|
||||
QFile infile(filename);
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
if (infile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QByteArray contents = infile.readAll();
|
||||
QDataStream qds(contents);
|
||||
for (int track = 0; track < 35; track++)
|
||||
{
|
||||
for (int sector = 0; sector < m_sectors_per_track; sector++)
|
||||
{
|
||||
char buffer[256];
|
||||
if (qds.readRawData(buffer,256) == 256)
|
||||
{
|
||||
Sector sec;
|
||||
sec.setTrackSector(track,sector);
|
||||
sec.setData(QByteArray(buffer,256));
|
||||
m_contents[track][sector] = sec;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Invalid sector read!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
hash.addData(contents);
|
||||
|
||||
m_hash = hash.result();
|
||||
qDebug() << "Hash: " << m_hash;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
qDebug() << "Could not open file " << filename;
|
||||
return false;
|
||||
}
|
||||
|
||||
VTOC DiskFile::getVTOC()
|
||||
{
|
||||
return getSector(17,0).promoteToVTOC();
|
||||
}
|
||||
|
||||
QList<CatalogSector> DiskFile::getCatalogSectors()
|
||||
{
|
||||
QList<CatalogSector> retval;
|
||||
VTOC vtoc = getVTOC();
|
||||
TSPair ts = vtoc.firstCatalogSector();
|
||||
|
||||
CatalogSector cs = getSector(ts).promoteToCatalogSector();
|
||||
retval.append(cs);
|
||||
while (cs.nextCatalogSector() != TSPair(0,0)) {
|
||||
ts = cs.nextCatalogSector();
|
||||
cs = getSector(ts).promoteToCatalogSector();
|
||||
retval.append(cs);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
GenericFile *DiskFile::getFile(FileDescriptiveEntry fde)
|
||||
{
|
||||
GenericFile *retval = 0;
|
||||
if (m_files.contains(fde))
|
||||
{
|
||||
retval = m_files[fde];
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackSectorList tsl = getSector(fde.firstTSListSector).promoteToTrackSectorList();
|
||||
QByteArray data = getDataFromTrackSectorList(tsl);
|
||||
|
||||
if (fde.fileType() == "A")
|
||||
{
|
||||
retval = new ApplesoftFile(data);
|
||||
}
|
||||
else if (fde.fileType() == "B")
|
||||
{
|
||||
retval = new BinaryFile(data);
|
||||
}
|
||||
else if (fde.fileType() == "R")
|
||||
{
|
||||
retval = new RelocatableFile(data);
|
||||
}
|
||||
else if ((fde.fileType() == "T"))
|
||||
{
|
||||
retval = new TextFile(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = new GenericFile(data);
|
||||
}
|
||||
m_files[fde] = retval;
|
||||
}
|
||||
if (retval) { retval->setDiskFile(this); }
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
QByteArray DiskFile::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||
{
|
||||
QByteArray retval;
|
||||
|
||||
foreach(TSPair pair, tsl.getDataTSPairs())
|
||||
{
|
||||
Sector sec = getSector(pair);
|
||||
retval.append(sec.rawData());
|
||||
}
|
||||
|
||||
if (tsl.getNextTSList() != TSPair(0,0)) {
|
||||
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).promoteToTrackSectorList();
|
||||
retval.append(getDataFromTrackSectorList(nextTsl));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
QList<FileDescriptiveEntry> DiskFile::getAllFDEs() {
|
||||
QList<FileDescriptiveEntry> retval;
|
||||
|
||||
QList<CatalogSector> sectors = getCatalogSectors();
|
||||
|
||||
foreach (CatalogSector cs, sectors)
|
||||
{
|
||||
QList<FileDescriptiveEntry> fdes = cs.getFDEs();
|
||||
retval.append(fdes);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
QString DiskFile::getMetaDataPath() const {
|
||||
QString path = QString("%1.metadata/").arg(getFullDiskImageName());
|
||||
|
||||
QDir dir(path);
|
||||
dir.mkpath(".");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
#include "diskfile.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
||||
#include "tracksectorlist.h"
|
||||
#include "applesoftfile.h"
|
||||
#include "binaryfile.h"
|
||||
#include "IntBasicFile.h"
|
||||
#include "relocatablefile.h"
|
||||
#include "textfile.h"
|
||||
|
||||
DiskFile::DiskFile(QString filename)
|
||||
{
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
read(filename);
|
||||
}
|
||||
}
|
||||
|
||||
DiskFile::~DiskFile()
|
||||
{
|
||||
foreach (GenericFile *file, m_files)
|
||||
{
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskFile::read(QString filename)
|
||||
{
|
||||
m_fullImageName = filename;
|
||||
m_imageName = QFileInfo(filename).fileName();
|
||||
if (m_imageName.toUpper().contains(".D13"))
|
||||
{
|
||||
m_sectors_per_track = 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sectors_per_track = 16;
|
||||
}
|
||||
|
||||
QFile infile(filename);
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
if (infile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QByteArray contents = infile.readAll();
|
||||
QDataStream qds(contents);
|
||||
for (int track = 0; track < 35; track++)
|
||||
{
|
||||
for (int sector = 0; sector < m_sectors_per_track; sector++)
|
||||
{
|
||||
char buffer[256];
|
||||
if (qds.readRawData(buffer,256) == 256)
|
||||
{
|
||||
Sector sec;
|
||||
sec.setTrackSector(track,sector);
|
||||
sec.setData(QByteArray(buffer,256));
|
||||
m_contents[track][sector] = sec;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Invalid sector read!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
hash.addData(contents);
|
||||
|
||||
m_hash = hash.result();
|
||||
qDebug() << "Hash: " << m_hash;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
qDebug() << "Could not open file " << filename;
|
||||
return false;
|
||||
}
|
||||
|
||||
VTOC DiskFile::getVTOC()
|
||||
{
|
||||
return getSector(17,0).promoteToVTOC();
|
||||
}
|
||||
|
||||
QList<CatalogSector> DiskFile::getCatalogSectors()
|
||||
{
|
||||
QList<CatalogSector> retval;
|
||||
VTOC vtoc = getVTOC();
|
||||
TSPair ts = vtoc.firstCatalogSector();
|
||||
|
||||
CatalogSector cs = getSector(ts).promoteToCatalogSector();
|
||||
retval.append(cs);
|
||||
while (cs.nextCatalogSector() != TSPair(0,0)) {
|
||||
ts = cs.nextCatalogSector();
|
||||
cs = getSector(ts).promoteToCatalogSector();
|
||||
retval.append(cs);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
GenericFile *DiskFile::getFile(FileDescriptiveEntry fde)
|
||||
{
|
||||
GenericFile *retval = 0;
|
||||
if (m_files.contains(fde))
|
||||
{
|
||||
retval = m_files[fde];
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackSectorList tsl = getSector(fde.firstTSListSector).promoteToTrackSectorList();
|
||||
QByteArray data = getDataFromTrackSectorList(tsl);
|
||||
|
||||
if (fde.fileType() == "A")
|
||||
{
|
||||
retval = new ApplesoftFile(data);
|
||||
}
|
||||
else if (fde.fileType() == "B")
|
||||
{
|
||||
retval = new BinaryFile(data);
|
||||
}
|
||||
else if (fde.fileType() == "R")
|
||||
{
|
||||
retval = new RelocatableFile(data);
|
||||
}
|
||||
else if ((fde.fileType() == "T"))
|
||||
{
|
||||
retval = new TextFile(data);
|
||||
}
|
||||
else if ((fde.fileType() == "I"))
|
||||
{
|
||||
retval = new IntBasicFile(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = new GenericFile(data);
|
||||
}
|
||||
m_files[fde] = retval;
|
||||
}
|
||||
if (retval) { retval->setDiskFile(this); }
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
QByteArray DiskFile::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||
{
|
||||
QByteArray retval;
|
||||
|
||||
foreach(TSPair pair, tsl.getDataTSPairs())
|
||||
{
|
||||
Sector sec = getSector(pair);
|
||||
retval.append(sec.rawData());
|
||||
}
|
||||
|
||||
if (tsl.getNextTSList() != TSPair(0,0)) {
|
||||
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).promoteToTrackSectorList();
|
||||
retval.append(getDataFromTrackSectorList(nextTsl));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
QList<FileDescriptiveEntry> DiskFile::getAllFDEs() {
|
||||
QList<FileDescriptiveEntry> retval;
|
||||
|
||||
QList<CatalogSector> sectors = getCatalogSectors();
|
||||
|
||||
foreach (CatalogSector cs, sectors)
|
||||
{
|
||||
QList<FileDescriptiveEntry> fdes = cs.getFDEs();
|
||||
retval.append(fdes);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
QString DiskFile::getMetaDataPath() const {
|
||||
QString path = QString("%1.metadata/").arg(getFullDiskImageName());
|
||||
|
||||
QDir dir(path);
|
||||
dir.mkpath(".");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -1,59 +1,59 @@
|
||||
#ifndef DISKFILE_H
|
||||
#define DISKFILE_H
|
||||
|
||||
#include <Qt>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include "util.h"
|
||||
#include "sector.h"
|
||||
#include "vtoc.h"
|
||||
|
||||
class GenericFile;
|
||||
|
||||
class DiskFile
|
||||
{
|
||||
public:
|
||||
DiskFile(QString filename = "");
|
||||
~DiskFile();
|
||||
|
||||
bool read(QString filename);
|
||||
|
||||
Sector &getSector(TSPair ts) { return getSector(ts.track, ts.sector); }
|
||||
|
||||
Sector &getSector(int track, int sector) {
|
||||
return m_contents[track][sector];
|
||||
}
|
||||
|
||||
VTOC getVTOC();
|
||||
|
||||
QList<CatalogSector> getCatalogSectors();
|
||||
|
||||
GenericFile *getFile(FileDescriptiveEntry fde);
|
||||
|
||||
QByteArray getDataFromTrackSectorList(TrackSectorList tsl);
|
||||
|
||||
QList<FileDescriptiveEntry> getAllFDEs();
|
||||
|
||||
QByteArray fileHash() const { return m_hash; }
|
||||
|
||||
QString getDiskImageName() const { return m_imageName; }
|
||||
QString getFullDiskImageName() const { return m_fullImageName; }
|
||||
QString getMetaDataPath() const;
|
||||
|
||||
private:
|
||||
|
||||
QMap< int, QMap< int, Sector> > m_contents;
|
||||
QMap<FileDescriptiveEntry,GenericFile *> m_files;
|
||||
QByteArray m_hash;
|
||||
|
||||
QString m_imageName;
|
||||
QString m_fullImageName;
|
||||
|
||||
quint8 m_sectors_per_track;
|
||||
|
||||
};
|
||||
|
||||
#endif // DISKFILE_H
|
||||
#ifndef DISKFILE_H
|
||||
#define DISKFILE_H
|
||||
|
||||
#include <Qt>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include "util.h"
|
||||
#include "sector.h"
|
||||
#include "vtoc.h"
|
||||
|
||||
class GenericFile;
|
||||
|
||||
class DiskFile
|
||||
{
|
||||
public:
|
||||
DiskFile(QString filename = "");
|
||||
~DiskFile();
|
||||
|
||||
bool read(QString filename);
|
||||
|
||||
Sector &getSector(TSPair ts) { return getSector(ts.track, ts.sector); }
|
||||
|
||||
Sector &getSector(int track, int sector) {
|
||||
return m_contents[track][sector];
|
||||
}
|
||||
|
||||
VTOC getVTOC();
|
||||
|
||||
QList<CatalogSector> getCatalogSectors();
|
||||
|
||||
GenericFile *getFile(FileDescriptiveEntry fde);
|
||||
|
||||
QByteArray getDataFromTrackSectorList(TrackSectorList tsl);
|
||||
|
||||
QList<FileDescriptiveEntry> getAllFDEs();
|
||||
|
||||
QByteArray fileHash() const { return m_hash; }
|
||||
|
||||
QString getDiskImageName() const { return m_imageName; }
|
||||
QString getFullDiskImageName() const { return m_fullImageName; }
|
||||
QString getMetaDataPath() const;
|
||||
|
||||
private:
|
||||
|
||||
QMap< int, QMap< int, Sector> > m_contents;
|
||||
QMap<FileDescriptiveEntry,GenericFile *> m_files;
|
||||
QByteArray m_hash;
|
||||
|
||||
QString m_imageName;
|
||||
QString m_fullImageName;
|
||||
|
||||
quint8 m_sectors_per_track;
|
||||
|
||||
};
|
||||
|
||||
#endif // DISKFILE_H
|
||||
|
@ -1,2 +1,2 @@
|
||||
#include "filedescriptiveentry.h"
|
||||
|
||||
#include "filedescriptiveentry.h"
|
||||
|
||||
|
@ -1,55 +1,55 @@
|
||||
#ifndef FILEDESCRIPTIVEENTRY_H
|
||||
#define FILEDESCRIPTIVEENTRY_H
|
||||
|
||||
#include "util.h"
|
||||
#include <QDebug>
|
||||
#include "applestring.h"
|
||||
|
||||
struct FileDescriptiveEntry {
|
||||
TSPair firstTSListSector;
|
||||
int fileTypeAndFlags;
|
||||
AppleString filename;
|
||||
quint16 lengthInSectors;
|
||||
bool deleted;
|
||||
|
||||
FileDescriptiveEntry() {
|
||||
fileTypeAndFlags = 0;
|
||||
lengthInSectors = 0;
|
||||
deleted = false;
|
||||
}
|
||||
|
||||
bool operator<(const FileDescriptiveEntry& f1) const {
|
||||
return f1.filename < filename;
|
||||
}
|
||||
|
||||
QString fileType() {
|
||||
if (fileTypeAndFlags & DOSIntegerBasicFile) { return "I"; }
|
||||
if (fileTypeAndFlags & DOSApplesoftBasicFile) { return "A"; }
|
||||
if (fileTypeAndFlags & DOSRelocatableFile) { return "R"; }
|
||||
if (fileTypeAndFlags & DOSRawBinaryFile) { return "B"; }
|
||||
if (fileTypeAndFlags & DOSTypeSFile) { return "S"; }
|
||||
if (fileTypeAndFlags & DOSTypeAFile) { return "a"; }
|
||||
if (fileTypeAndFlags & DOSTypeBFile) { return "b"; }
|
||||
return "T";
|
||||
}
|
||||
|
||||
bool isLocked() { return (fileTypeAndFlags & DOSIsLocked); }
|
||||
|
||||
void dump() {
|
||||
qDebug() << "First TS List Sector: Track: " << QString("%1").arg(firstTSListSector.track,2,16,QChar('0')).toUpper()
|
||||
<< " Sector: " << QString("%1").arg(firstTSListSector.sector,2,16,QChar('0')).toUpper();
|
||||
qDebug() << "File Type and Flags: " << QString::number((quint8)fileTypeAndFlags) << "(" << fileType() << "," << (isLocked()?"Locked":"Unlocked") << ")";
|
||||
qDebug() << "Filename: " << filename.printable();
|
||||
qDebug() << "Length in Sectors: " << lengthInSectors;
|
||||
}
|
||||
|
||||
void catalog() {
|
||||
QString output = QString("%1 %2 %3 %4").arg(QString(isLocked()?"*":" "))
|
||||
.arg(lengthInSectors,3,10,QChar('0'))
|
||||
.arg(fileType())
|
||||
.arg(filename.printable().trimmed());
|
||||
qDebug() << output;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // FILEDESCRIPTIVEENTRY_H
|
||||
#ifndef FILEDESCRIPTIVEENTRY_H
|
||||
#define FILEDESCRIPTIVEENTRY_H
|
||||
|
||||
#include "util.h"
|
||||
#include <QDebug>
|
||||
#include "applestring.h"
|
||||
|
||||
struct FileDescriptiveEntry {
|
||||
TSPair firstTSListSector;
|
||||
int fileTypeAndFlags;
|
||||
AppleString filename;
|
||||
quint16 lengthInSectors;
|
||||
bool deleted;
|
||||
|
||||
FileDescriptiveEntry() {
|
||||
fileTypeAndFlags = 0;
|
||||
lengthInSectors = 0;
|
||||
deleted = false;
|
||||
}
|
||||
|
||||
bool operator<(const FileDescriptiveEntry& f1) const {
|
||||
return f1.filename < filename;
|
||||
}
|
||||
|
||||
QString fileType() {
|
||||
if (fileTypeAndFlags & DOSIntegerBasicFile) { return "I"; }
|
||||
if (fileTypeAndFlags & DOSApplesoftBasicFile) { return "A"; }
|
||||
if (fileTypeAndFlags & DOSRelocatableFile) { return "R"; }
|
||||
if (fileTypeAndFlags & DOSRawBinaryFile) { return "B"; }
|
||||
if (fileTypeAndFlags & DOSTypeSFile) { return "S"; }
|
||||
if (fileTypeAndFlags & DOSTypeAFile) { return "a"; }
|
||||
if (fileTypeAndFlags & DOSTypeBFile) { return "b"; }
|
||||
return "T";
|
||||
}
|
||||
|
||||
bool isLocked() { return (fileTypeAndFlags & DOSIsLocked); }
|
||||
|
||||
void dump() {
|
||||
qDebug() << "First TS List Sector: Track: " << QString("%1").arg(firstTSListSector.track,2,16,QChar('0')).toUpper()
|
||||
<< " Sector: " << QString("%1").arg(firstTSListSector.sector,2,16,QChar('0')).toUpper();
|
||||
qDebug() << "File Type and Flags: " << QString::number((quint8)fileTypeAndFlags) << "(" << fileType() << "," << (isLocked()?"Locked":"Unlocked") << ")";
|
||||
qDebug() << "Filename: " << filename.printable();
|
||||
qDebug() << "Length in Sectors: " << lengthInSectors;
|
||||
}
|
||||
|
||||
void catalog() {
|
||||
QString output = QString("%1 %2 %3 %4").arg(QString(isLocked()?"*":" "))
|
||||
.arg(lengthInSectors,3,10,QChar('0'))
|
||||
.arg(fileType())
|
||||
.arg(filename.printable().trimmed());
|
||||
qDebug() << output;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // FILEDESCRIPTIVEENTRY_H
|
||||
|
@ -1,17 +1,17 @@
|
||||
#include "genericfile.h"
|
||||
|
||||
GenericFile::GenericFile(QByteArray data)
|
||||
{
|
||||
m_diskfile = 0;
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
}
|
||||
m_address = 0x00;
|
||||
m_length = 0x00;
|
||||
}
|
||||
|
||||
void GenericFile::setData(QByteArray data)
|
||||
{
|
||||
m_data = data;
|
||||
m_length = data.size();
|
||||
}
|
||||
#include "genericfile.h"
|
||||
|
||||
GenericFile::GenericFile(QByteArray data)
|
||||
{
|
||||
m_diskfile = 0;
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
}
|
||||
m_address = 0x00;
|
||||
m_length = 0x00;
|
||||
}
|
||||
|
||||
void GenericFile::setData(QByteArray data)
|
||||
{
|
||||
m_data = data;
|
||||
m_length = data.size();
|
||||
}
|
||||
|
@ -1,39 +1,42 @@
|
||||
#ifndef GENERICFILE_H
|
||||
#define GENERICFILE_H
|
||||
|
||||
#include "diskfile.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
|
||||
class GenericFile
|
||||
{
|
||||
public:
|
||||
GenericFile(QByteArray data = QByteArray());
|
||||
virtual ~GenericFile() { }
|
||||
virtual void setData(QByteArray data);
|
||||
|
||||
virtual QByteArray data() { return m_data; }
|
||||
void setFilename(QString filename) { m_filename = filename; }
|
||||
QString filename() const { return m_filename; }
|
||||
virtual void setAddress(quint16 location) { m_address = location; }
|
||||
virtual quint16 address() { return m_address; }
|
||||
virtual QByteArray rawData() { return m_data; }
|
||||
|
||||
virtual void setLength(quint16 length) { m_length = length; }
|
||||
virtual quint16 length() { return m_length; }
|
||||
|
||||
DiskFile *diskFile() const { return m_diskfile; }
|
||||
void setDiskFile(DiskFile *diskfile) { m_diskfile = diskfile; }
|
||||
|
||||
protected:
|
||||
QByteArray m_data;
|
||||
QString m_filename;
|
||||
quint16 m_address;
|
||||
qint16 m_length;
|
||||
DiskFile * m_diskfile;
|
||||
|
||||
};
|
||||
|
||||
#endif // GENERICFILE_H
|
||||
#ifndef GENERICFILE_H
|
||||
#define GENERICFILE_H
|
||||
|
||||
#include "diskfile.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
|
||||
class GenericFile
|
||||
{
|
||||
public:
|
||||
GenericFile(QByteArray data = QByteArray());
|
||||
virtual ~GenericFile() { }
|
||||
|
||||
virtual void setData(QByteArray data);
|
||||
virtual QByteArray data() { return m_data; }
|
||||
|
||||
void setFilename(QString filename) { m_filename = filename; }
|
||||
QString filename() const { return m_filename; }
|
||||
|
||||
virtual void setAddress(quint16 location) { m_address = location; }
|
||||
virtual quint16 address() { return m_address; }
|
||||
|
||||
virtual QByteArray rawData() { return m_data; }
|
||||
|
||||
virtual void setLength(quint16 length) { m_length = length; }
|
||||
virtual quint16 length() const { return m_length; }
|
||||
|
||||
DiskFile *diskFile() const { return m_diskfile; }
|
||||
void setDiskFile(DiskFile *diskfile) { m_diskfile = diskfile; }
|
||||
|
||||
protected:
|
||||
QByteArray m_data;
|
||||
QString m_filename;
|
||||
quint16 m_address;
|
||||
qint16 m_length;
|
||||
DiskFile * m_diskfile;
|
||||
|
||||
};
|
||||
|
||||
#endif // GENERICFILE_H
|
||||
|
@ -1,47 +1,47 @@
|
||||
#include "sector.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
QByteRef Sector::operator[](uint offset) {
|
||||
if (offset > 255) {
|
||||
offset = 255;
|
||||
}
|
||||
return m_data[offset];
|
||||
}
|
||||
|
||||
bool Sector::setData(QByteArray data) {
|
||||
if (data.length() != 256) return false;
|
||||
|
||||
m_data = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sector::dump() {
|
||||
qDebug() << "Dumping Track " << track() << "Sector " << sector() << " ...";
|
||||
for (int jdx = 0; jdx < 16; jdx++)
|
||||
{
|
||||
QString line;
|
||||
line += QString("%1 (%2): ").arg(jdx*16,2,16,QChar('0')).arg(jdx*16,3,10,QChar(' '));
|
||||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_data[offset];
|
||||
line += QString("%1 ").arg(val,2,16,QChar('0'));
|
||||
if (idx == 7) line += " ";
|
||||
}
|
||||
line = line.toUpper();
|
||||
line += " ";
|
||||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_data[offset];
|
||||
if (val > 127) { val -= 128; }
|
||||
QChar ch(val);
|
||||
line += QString("%1").arg(ch.isPrint()?ch:'.');
|
||||
}
|
||||
|
||||
qDebug() << line;
|
||||
}
|
||||
}
|
||||
|
||||
#include "sector.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
QByteRef Sector::operator[](uint offset) {
|
||||
if (offset > 255) {
|
||||
offset = 255;
|
||||
}
|
||||
return m_data[offset];
|
||||
}
|
||||
|
||||
bool Sector::setData(QByteArray data) {
|
||||
if (data.length() != 256) return false;
|
||||
|
||||
m_data = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sector::dump() {
|
||||
qDebug() << "Dumping Track " << track() << "Sector " << sector() << " ...";
|
||||
for (int jdx = 0; jdx < 16; jdx++)
|
||||
{
|
||||
QString line;
|
||||
line += QString("%1 (%2): ").arg(jdx*16,2,16,QChar('0')).arg(jdx*16,3,10,QChar(' '));
|
||||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_data[offset];
|
||||
line += QString("%1 ").arg(val,2,16,QChar('0'));
|
||||
if (idx == 7) line += " ";
|
||||
}
|
||||
line = line.toUpper();
|
||||
line += " ";
|
||||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_data[offset];
|
||||
if (val > 127) { val -= 128; }
|
||||
QChar ch(val);
|
||||
line += QString("%1").arg(ch.isPrint()?ch:'.');
|
||||
}
|
||||
|
||||
qDebug() << line;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,57 +1,57 @@
|
||||
#ifndef SECTOR_H
|
||||
#define SECTOR_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "vtoc.h"
|
||||
#include "catalogsector.h"
|
||||
#include "tracksectorlist.h"
|
||||
|
||||
class Sector
|
||||
{
|
||||
public:
|
||||
|
||||
Sector() {
|
||||
m_data.resize(256);
|
||||
m_track = 255;
|
||||
m_sector = 255;
|
||||
}
|
||||
|
||||
VTOC promoteToVTOC() {
|
||||
return VTOC(this);
|
||||
}
|
||||
|
||||
CatalogSector promoteToCatalogSector() {
|
||||
return CatalogSector(this);
|
||||
}
|
||||
|
||||
TrackSectorList promoteToTrackSectorList() {
|
||||
return TrackSectorList(this);
|
||||
}
|
||||
|
||||
int sector() { return m_sector; }
|
||||
int track() { return m_track; }
|
||||
|
||||
void setTrackSector(int track, int sector) {
|
||||
setTrack(track);
|
||||
setSector(sector);
|
||||
}
|
||||
|
||||
void setTrack(int track) { m_track = track; }
|
||||
void setSector(int sector) { m_sector = sector; }
|
||||
|
||||
QByteRef operator[](uint offset);
|
||||
|
||||
bool setData(QByteArray data);
|
||||
|
||||
void dump();
|
||||
|
||||
QByteArray rawData() { return m_data; }
|
||||
|
||||
private:
|
||||
QByteArray m_data;
|
||||
int m_track;
|
||||
int m_sector;
|
||||
};
|
||||
|
||||
#endif // SECTOR_H
|
||||
#ifndef SECTOR_H
|
||||
#define SECTOR_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "vtoc.h"
|
||||
#include "catalogsector.h"
|
||||
#include "tracksectorlist.h"
|
||||
|
||||
class Sector
|
||||
{
|
||||
public:
|
||||
|
||||
Sector() {
|
||||
m_data.resize(256);
|
||||
m_track = 255;
|
||||
m_sector = 255;
|
||||
}
|
||||
|
||||
VTOC promoteToVTOC() {
|
||||
return VTOC(this);
|
||||
}
|
||||
|
||||
CatalogSector promoteToCatalogSector() {
|
||||
return CatalogSector(this);
|
||||
}
|
||||
|
||||
TrackSectorList promoteToTrackSectorList() {
|
||||
return TrackSectorList(this);
|
||||
}
|
||||
|
||||
int sector() { return m_sector; }
|
||||
int track() { return m_track; }
|
||||
|
||||
void setTrackSector(int track, int sector) {
|
||||
setTrack(track);
|
||||
setSector(sector);
|
||||
}
|
||||
|
||||
void setTrack(int track) { m_track = track; }
|
||||
void setSector(int sector) { m_sector = sector; }
|
||||
|
||||
QByteRef operator[](uint offset);
|
||||
|
||||
bool setData(QByteArray data);
|
||||
|
||||
void dump();
|
||||
|
||||
QByteArray rawData() { return m_data; }
|
||||
|
||||
private:
|
||||
QByteArray m_data;
|
||||
int m_track;
|
||||
int m_sector;
|
||||
};
|
||||
|
||||
#endif // SECTOR_H
|
||||
|
@ -1,24 +1,24 @@
|
||||
#include "tracksectorlist.h"
|
||||
|
||||
#include "sector.h"
|
||||
|
||||
TrackSectorList::TrackSectorList(Sector *data)
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
m_next_tslist.track = m_data->rawData()[0x01];
|
||||
m_next_tslist.sector = m_data->rawData()[0x02];
|
||||
|
||||
m_sector_offset.track = m_data->rawData()[0x05];
|
||||
m_sector_offset.sector = m_data->rawData()[0x06];
|
||||
|
||||
for (int idx = 0x0C; idx < 0xff; idx+=2)
|
||||
{
|
||||
TSPair ts(m_data->rawData()[idx],m_data->rawData()[idx+1]);
|
||||
if (ts == TSPair(0,0)) {
|
||||
break;
|
||||
} else {
|
||||
m_ts_pairs_for_data.append(ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "tracksectorlist.h"
|
||||
|
||||
#include "sector.h"
|
||||
|
||||
TrackSectorList::TrackSectorList(Sector *data)
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
m_next_tslist.track = m_data->rawData()[0x01];
|
||||
m_next_tslist.sector = m_data->rawData()[0x02];
|
||||
|
||||
m_sector_offset.track = m_data->rawData()[0x05];
|
||||
m_sector_offset.sector = m_data->rawData()[0x06];
|
||||
|
||||
for (int idx = 0x0C; idx < 0xff; idx+=2)
|
||||
{
|
||||
TSPair ts(m_data->rawData()[idx],m_data->rawData()[idx+1]);
|
||||
if (ts == TSPair(0,0)) {
|
||||
break;
|
||||
} else {
|
||||
m_ts_pairs_for_data.append(ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
#ifndef TRACKSECTORLIST_H
|
||||
#define TRACKSECTORLIST_H
|
||||
|
||||
#include "util.h"
|
||||
|
||||
class Sector;
|
||||
|
||||
class TrackSectorList
|
||||
{
|
||||
public:
|
||||
TrackSectorList(Sector *data);
|
||||
|
||||
TSPair getNextTSList() const { return m_next_tslist; }
|
||||
TSPair getSectorOffset() const { return m_sector_offset; }
|
||||
|
||||
QList<TSPair> getDataTSPairs() { return m_ts_pairs_for_data; }
|
||||
|
||||
private:
|
||||
|
||||
TSPair m_next_tslist;
|
||||
TSPair m_sector_offset;
|
||||
QList<TSPair> m_ts_pairs_for_data;
|
||||
|
||||
Sector *m_data;
|
||||
};
|
||||
|
||||
#endif // TRACKSECTORLIST_H
|
||||
#ifndef TRACKSECTORLIST_H
|
||||
#define TRACKSECTORLIST_H
|
||||
|
||||
#include "util.h"
|
||||
|
||||
class Sector;
|
||||
|
||||
class TrackSectorList
|
||||
{
|
||||
public:
|
||||
TrackSectorList(Sector *data);
|
||||
|
||||
TSPair getNextTSList() const { return m_next_tslist; }
|
||||
TSPair getSectorOffset() const { return m_sector_offset; }
|
||||
|
||||
QList<TSPair> getDataTSPairs() { return m_ts_pairs_for_data; }
|
||||
|
||||
private:
|
||||
|
||||
TSPair m_next_tslist;
|
||||
TSPair m_sector_offset;
|
||||
QList<TSPair> m_ts_pairs_for_data;
|
||||
|
||||
Sector *m_data;
|
||||
};
|
||||
|
||||
#endif // TRACKSECTORLIST_H
|
||||
|
@ -1,99 +1,100 @@
|
||||
#include "vtoc.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
#include "sector.h"
|
||||
#include "util.h"
|
||||
|
||||
VTOC::VTOC(Sector *data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
TSPair VTOC::firstCatalogSector() {
|
||||
return TSPair(m_data->rawData()[0x01], m_data->rawData()[0x02]);
|
||||
}
|
||||
|
||||
quint8 VTOC::dosVersion() {
|
||||
return m_data->rawData()[0x03];
|
||||
}
|
||||
|
||||
quint8 VTOC::volumeNumber() {
|
||||
return m_data->rawData()[0x06];
|
||||
}
|
||||
|
||||
quint8 VTOC::maxTSPairs() {
|
||||
return m_data->rawData()[0x27];
|
||||
}
|
||||
|
||||
quint8 VTOC::lastTrackAllocated() {
|
||||
return m_data->rawData()[0x30];
|
||||
}
|
||||
|
||||
qint8 VTOC::directionOfAllocation() {
|
||||
return m_data->rawData()[0x31];
|
||||
}
|
||||
|
||||
quint8 VTOC::tracksPerDisk() {
|
||||
return m_data->rawData()[0x34];
|
||||
}
|
||||
|
||||
quint8 VTOC::sectorsPerDisk() {
|
||||
return m_data->rawData()[0x35];
|
||||
}
|
||||
|
||||
qint16 VTOC::bytesPerSector() {
|
||||
return makeWord(m_data->rawData()[0x36],
|
||||
m_data->rawData()[0x37]);
|
||||
}
|
||||
|
||||
bool VTOC::isSectorInUse(TSPair ts) {
|
||||
quint8 track = ts.track;
|
||||
quint8 sec = ts.sector;
|
||||
quint8 baseaddr = (track * 4) + 0x38;
|
||||
|
||||
//quint16 word = (((quint16) m_data->rawData()[baseaddr]) *256) + (quint8) m_data->rawData()[baseaddr+1];
|
||||
quint16 word = makeWord(m_data->rawData()[baseaddr+1],m_data->rawData()[baseaddr]);
|
||||
quint16 bitpos = (quint16) 0x01 << (quint16) sec;
|
||||
|
||||
return !(word & bitpos);
|
||||
}
|
||||
|
||||
void VTOC::dump()
|
||||
{
|
||||
/*
|
||||
for (qint8 idx = 0x0f; idx >= 0; idx--) {
|
||||
quint8 shift;
|
||||
if (idx < 0x08) { shift = idx; } else { shift = idx-0x08; }
|
||||
qDebug() << "Idx: " << idx << "Shift: " << (quint8) shift << "Bitpos: " << (quint8) (0x01 << shift);
|
||||
}
|
||||
*/
|
||||
qDebug() << "Dumping VTOC Track " << m_data->track() << "Sector " << m_data->sector() << " ...";
|
||||
qDebug() << " Track number of first catalog sector: " << QString::number(firstCatalogSector().track);
|
||||
qDebug() << " Sector number of first catalog sector: " << QString::number(firstCatalogSector().sector);
|
||||
qDebug() << " Release number of DOS used to INIT disk: " << QString::number(dosVersion());
|
||||
qDebug() << " Disk Volume Number: " << QString::number(volumeNumber());
|
||||
qDebug() << " Max track/sector pairs that fit in t/s list sector (122=256): " << QString::number(maxTSPairs());
|
||||
qDebug() << " Last track where sectors were allocated: " << QString::number(lastTrackAllocated());
|
||||
qDebug() << " Direction of track allocations (+/- 1): " << QString::number(directionOfAllocation());
|
||||
qDebug() << " Number tracks per disk: " << QString::number(tracksPerDisk());
|
||||
qDebug() << " Number sectors per disk: " << QString::number(sectorsPerDisk());
|
||||
qDebug() << " Number bytes/sector: " << QString::number(bytesPerSector());
|
||||
qDebug() << " Track Usage (.=free, 0-F=used):";
|
||||
for (quint8 track = 0; track < m_data->rawData()[0x34];track++)
|
||||
{
|
||||
qDebug() << " " << QString("Track %1:").arg((int) track,2,10,QChar('0')) << buildUseString(track);
|
||||
}
|
||||
}
|
||||
|
||||
QString VTOC::buildUseString(quint8 track) {
|
||||
QString usestr;
|
||||
for (qint8 sec = 0x0f; sec >= 0; sec--)
|
||||
{
|
||||
usestr.append(isSectorInUse(TSPair(track,sec))?QString::number(sec,16).toUpper():"-");
|
||||
}
|
||||
return usestr;
|
||||
}
|
||||
|
||||
|
||||
#include "vtoc.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
#include "sector.h"
|
||||
#include "util.h"
|
||||
|
||||
VTOC::VTOC(Sector *data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
TSPair VTOC::firstCatalogSector() {
|
||||
return TSPair(m_data->rawData()[0x01], m_data->rawData()[0x02]);
|
||||
}
|
||||
|
||||
quint8 VTOC::dosVersion() {
|
||||
return m_data->rawData()[0x03];
|
||||
}
|
||||
|
||||
quint8 VTOC::volumeNumber() {
|
||||
return m_data->rawData()[0x06];
|
||||
}
|
||||
|
||||
quint8 VTOC::maxTSPairs() {
|
||||
return m_data->rawData()[0x27];
|
||||
}
|
||||
|
||||
quint8 VTOC::lastTrackAllocated() {
|
||||
return m_data->rawData()[0x30];
|
||||
}
|
||||
|
||||
qint8 VTOC::directionOfAllocation() {
|
||||
return m_data->rawData()[0x31];
|
||||
}
|
||||
|
||||
quint8 VTOC::tracksPerDisk() {
|
||||
return m_data->rawData()[0x34];
|
||||
}
|
||||
|
||||
quint8 VTOC::sectorsPerDisk() {
|
||||
return m_data->rawData()[0x35];
|
||||
}
|
||||
|
||||
qint16 VTOC::bytesPerSector() {
|
||||
return makeWord(m_data->rawData()[0x36],
|
||||
m_data->rawData()[0x37]);
|
||||
}
|
||||
|
||||
bool VTOC::isSectorInUse(TSPair ts) {
|
||||
quint8 track = ts.track;
|
||||
quint8 sec = ts.sector;
|
||||
quint8 baseaddr = (track * 4) + 0x38;
|
||||
|
||||
//quint16 word = (((quint16) m_data->rawData()[baseaddr]) *256) + (quint8) m_data->rawData()[baseaddr+1];
|
||||
quint16 word = makeWord(m_data->rawData()[baseaddr+1],
|
||||
m_data->rawData()[baseaddr]);
|
||||
quint16 bitpos = (quint16) 0x01 << (quint16) sec;
|
||||
|
||||
return !(word & bitpos);
|
||||
}
|
||||
|
||||
void VTOC::dump()
|
||||
{
|
||||
/*
|
||||
for (qint8 idx = 0x0f; idx >= 0; idx--) {
|
||||
quint8 shift;
|
||||
if (idx < 0x08) { shift = idx; } else { shift = idx-0x08; }
|
||||
qDebug() << "Idx: " << idx << "Shift: " << (quint8) shift << "Bitpos: " << (quint8) (0x01 << shift);
|
||||
}
|
||||
*/
|
||||
qDebug() << "Dumping VTOC Track " << m_data->track() << "Sector " << m_data->sector() << " ...";
|
||||
qDebug() << " Track number of first catalog sector: " << QString::number(firstCatalogSector().track);
|
||||
qDebug() << " Sector number of first catalog sector: " << QString::number(firstCatalogSector().sector);
|
||||
qDebug() << " Release number of DOS used to INIT disk: " << QString::number(dosVersion());
|
||||
qDebug() << " Disk Volume Number: " << QString::number(volumeNumber());
|
||||
qDebug() << " Max track/sector pairs that fit in t/s list sector (122=256): " << QString::number(maxTSPairs());
|
||||
qDebug() << " Last track where sectors were allocated: " << QString::number(lastTrackAllocated());
|
||||
qDebug() << " Direction of track allocations (+/- 1): " << QString::number(directionOfAllocation());
|
||||
qDebug() << " Number tracks per disk: " << QString::number(tracksPerDisk());
|
||||
qDebug() << " Number sectors per disk: " << QString::number(sectorsPerDisk());
|
||||
qDebug() << " Number bytes/sector: " << QString::number(bytesPerSector());
|
||||
qDebug() << " Track Usage (.=free, 0-F=used):";
|
||||
for (quint8 track = 0; track < m_data->rawData()[0x34];track++)
|
||||
{
|
||||
qDebug() << " " << QString("Track %1:").arg((int) track,2,10,QChar('0')) << buildUseString(track);
|
||||
}
|
||||
}
|
||||
|
||||
QString VTOC::buildUseString(quint8 track) {
|
||||
QString usestr;
|
||||
for (qint8 sec = 0x0f; sec >= 0; sec--)
|
||||
{
|
||||
usestr.append(isSectorInUse(TSPair(track,sec))?QString::number(sec,16).toUpper():"-");
|
||||
}
|
||||
return usestr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,33 +1,33 @@
|
||||
#ifndef VTOC_H
|
||||
#define VTOC_H
|
||||
|
||||
#include <Qt>
|
||||
#include "util.h"
|
||||
class Sector;
|
||||
class QString;
|
||||
|
||||
|
||||
class VTOC
|
||||
{
|
||||
public:
|
||||
VTOC(Sector *data);
|
||||
|
||||
void dump();
|
||||
TSPair firstCatalogSector();
|
||||
quint8 dosVersion();
|
||||
quint8 volumeNumber();
|
||||
quint8 maxTSPairs();
|
||||
quint8 lastTrackAllocated();
|
||||
qint8 directionOfAllocation();
|
||||
quint8 tracksPerDisk();
|
||||
quint8 sectorsPerDisk();
|
||||
qint16 bytesPerSector();
|
||||
bool isSectorInUse(TSPair ts);
|
||||
|
||||
private:
|
||||
QString buildUseString(quint8 track);
|
||||
|
||||
Sector *m_data;
|
||||
};
|
||||
|
||||
#endif // VTOC_H
|
||||
#ifndef VTOC_H
|
||||
#define VTOC_H
|
||||
|
||||
#include <Qt>
|
||||
#include "util.h"
|
||||
class Sector;
|
||||
class QString;
|
||||
|
||||
|
||||
class VTOC
|
||||
{
|
||||
public:
|
||||
VTOC(Sector *data);
|
||||
|
||||
void dump();
|
||||
TSPair firstCatalogSector();
|
||||
quint8 dosVersion();
|
||||
quint8 volumeNumber();
|
||||
quint8 maxTSPairs();
|
||||
quint8 lastTrackAllocated();
|
||||
qint8 directionOfAllocation();
|
||||
quint8 tracksPerDisk();
|
||||
quint8 sectorsPerDisk();
|
||||
qint16 bytesPerSector();
|
||||
bool isSectorInUse(TSPair ts);
|
||||
|
||||
private:
|
||||
QString buildUseString(quint8 track);
|
||||
|
||||
Sector *m_data;
|
||||
};
|
||||
|
||||
#endif // VTOC_H
|
||||
|
@ -26,6 +26,10 @@ quint16 IntBasicFile::get16(quint8 v1, quint8 v2)
|
||||
|
||||
QByteArray IntBasicFile::dumpBufferAsIntBasicFile(QByteArray origdata)
|
||||
/*
|
||||
* THIS CODE IS MODIFIED FROM PAUL SCHYLTER'S SAMPLE CODE AVAILABLE AT:
|
||||
* https://macgui.com/usenet/?group=1&start=14720&id=184603
|
||||
*
|
||||
*
|
||||
* Integer Basic file format:
|
||||
*
|
||||
* <Length_of_file> (16-bit little endian)
|
||||
|
@ -1,173 +1,173 @@
|
||||
#include "JumpLineManager.h"
|
||||
|
||||
JumpLineManager::JumpLineManager(quint16 from, quint16 to)
|
||||
: m_start(from),
|
||||
m_end(to)
|
||||
{
|
||||
//qDebug() << "JumpLineManager(from:"<<uint16ToHex(m_start)<<", to:"<<uint16ToHex(m_end) << ")";
|
||||
|
||||
}
|
||||
|
||||
void JumpLineManager::addJump(quint16 src, quint16 dest, JumpType type, quint16 from, quint16 to)
|
||||
{
|
||||
TJump jump(src,dest);
|
||||
if (src >= from && src <= to && dest >= from && dest <= to)
|
||||
{
|
||||
if (!m_jumpmap.contains(jump))
|
||||
{
|
||||
// qDebug() << "JumpLineManager::addJump: Added Jump from" << uint16ToHex(src) << "to" << uint16ToHex(dest) << ", Type:" << type;
|
||||
m_jumpmap.insert(jump,type);
|
||||
}
|
||||
else
|
||||
{
|
||||
//qDebug() << "JumpLineManager::addJump: Not adding duplicate jump:" << uint16ToHex(src) << "," << uint16ToHex(dest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// qDebug() << "JumpLineManager::addJump: Address range is out of bounds";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void JumpLineManager::dumpJumps() const {
|
||||
dumpJumps(m_jumpmap);
|
||||
}
|
||||
|
||||
void JumpLineManager::dumpJumps(JumpMap map) const
|
||||
{
|
||||
//qDebug() << "JumpLineManager::dumpJumps()\n JumpTable:";
|
||||
QMapIterator<TJump,JumpType> it(map);
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
QString jumptypelabel;
|
||||
if (it.value() == IsUnknownJump) { jumptypelabel = "Unknown Jump"; }
|
||||
if (it.value() == IsJMP) { jumptypelabel = "JMP"; }
|
||||
if (it.value() == IsBranch) { jumptypelabel = "Branch"; }
|
||||
if (it.value() == IsJSR) { jumptypelabel = "JSR"; }
|
||||
if (it.value() == IsBRA) { jumptypelabel = "BRA"; }
|
||||
//qDebug() << " Jump from" << uint16ToHex(it.key().first) << "to"
|
||||
// << uint16ToHex(it.key().second) << jumptypelabel;
|
||||
}
|
||||
}
|
||||
|
||||
JumpLines JumpLineManager::buildJumpLines()
|
||||
{
|
||||
//qDebug() << "A";
|
||||
|
||||
m_channelsAtAddress.clear();
|
||||
m_jumplines.m_maxChannel = 0;
|
||||
QMapIterator<TJump, JumpType> it(m_jumpmap);
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
TJump range = it.key();
|
||||
|
||||
JumpLine jl;
|
||||
jl.type = it.value();
|
||||
jl.from = range.first;
|
||||
jl.to = range.second;
|
||||
int channel = findBestChannel(jl);
|
||||
setChannelForJumpLine(channel,jl);
|
||||
|
||||
m_jumplines.jumpLines.append(jl);
|
||||
m_jumplines.m_maxChannel = qMax(m_jumplines.m_maxChannel, channel);
|
||||
}
|
||||
//qDebug() << "A";
|
||||
|
||||
|
||||
return m_jumplines;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int JumpLineManager::findBestChannel(JumpLine &jl)
|
||||
{
|
||||
//qDebug() << "findBestChannel()";
|
||||
if (m_jumplines.jumpLines.count() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int potentialChannel = 0;
|
||||
bool foundChannel = false;
|
||||
while (!foundChannel)
|
||||
{
|
||||
//qDebug() << "Tryning potential channel" << potentialChannel;
|
||||
bool matched = false;
|
||||
for (quint16 addr = jl.min(); addr <= jl.max(); addr++)
|
||||
{
|
||||
// If any of these addresses contain the potential channel, move on
|
||||
if (m_channelsAtAddress[addr].contains(potentialChannel))
|
||||
{
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
if (matched)
|
||||
{
|
||||
potentialChannel++;
|
||||
matched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
foundChannel = true;
|
||||
}
|
||||
}
|
||||
return potentialChannel;
|
||||
}
|
||||
|
||||
void JumpLineManager::setChannelForJumpLine(int channel, JumpLine &jl)
|
||||
{
|
||||
jl.channel = channel;
|
||||
for (quint16 addr = jl.min(); addr <= jl.max(); addr++)
|
||||
{
|
||||
m_channelsAtAddress[addr].append(channel);
|
||||
}
|
||||
}
|
||||
|
||||
void JumpLineManager::dumpJumpLines() const
|
||||
{
|
||||
//foreach (JumpLine jl, m_jumplines.jumpLines)
|
||||
// {
|
||||
//qDebug() << " JumpLine from:" << uint16ToHex(jl.from)
|
||||
// << " to:" << uint16ToHex(jl.to)
|
||||
// << "channel: " << jl.channel << " type:" << jl.type;
|
||||
// }
|
||||
}
|
||||
|
||||
bool JumpLineManager::doJumpsIntersect(TJump &A, TJump &B) const
|
||||
{
|
||||
|
||||
if (A == B) return false;
|
||||
if (isLineWithinRange(A.first,B) || isLineWithinRange(A.second,B))
|
||||
return true;
|
||||
|
||||
if (isLineWithinRange(B.first,A) || isLineWithinRange(B.second,A))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool JumpLineManager::isLineWithinRange(quint16 line, TJump &jm) const
|
||||
{
|
||||
quint16 min = qMin(jm.first,jm.second);
|
||||
quint16 max = qMax(jm.first,jm.second);
|
||||
|
||||
return (line > min && line < max);
|
||||
}
|
||||
|
||||
QList<JumpLine> JumpLines::jumpLinesAtAddress(quint16 addrs)
|
||||
{
|
||||
QList<JumpLine> list;
|
||||
foreach (JumpLine jl, jumpLines)
|
||||
{
|
||||
if (addrs >= jl.min() && addrs <= jl.max())
|
||||
{
|
||||
list.append(jl);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
#include "JumpLineManager.h"
|
||||
|
||||
JumpLineManager::JumpLineManager(quint16 from, quint16 to)
|
||||
: m_start(from),
|
||||
m_end(to)
|
||||
{
|
||||
//qDebug() << "JumpLineManager(from:"<<uint16ToHex(m_start)<<", to:"<<uint16ToHex(m_end) << ")";
|
||||
|
||||
}
|
||||
|
||||
void JumpLineManager::addJump(quint16 src, quint16 dest, JumpType type, quint16 from, quint16 to)
|
||||
{
|
||||
TJump jump(src,dest);
|
||||
if (src >= from && src <= to && dest >= from && dest <= to)
|
||||
{
|
||||
if (!m_jumpmap.contains(jump))
|
||||
{
|
||||
// qDebug() << "JumpLineManager::addJump: Added Jump from" << uint16ToHex(src) << "to" << uint16ToHex(dest) << ", Type:" << type;
|
||||
m_jumpmap.insert(jump,type);
|
||||
}
|
||||
else
|
||||
{
|
||||
//qDebug() << "JumpLineManager::addJump: Not adding duplicate jump:" << uint16ToHex(src) << "," << uint16ToHex(dest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// qDebug() << "JumpLineManager::addJump: Address range is out of bounds";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void JumpLineManager::dumpJumps() const {
|
||||
dumpJumps(m_jumpmap);
|
||||
}
|
||||
|
||||
void JumpLineManager::dumpJumps(JumpMap map) const
|
||||
{
|
||||
//qDebug() << "JumpLineManager::dumpJumps()\n JumpTable:";
|
||||
QMapIterator<TJump,JumpType> it(map);
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
QString jumptypelabel;
|
||||
if (it.value() == IsUnknownJump) { jumptypelabel = "Unknown Jump"; }
|
||||
if (it.value() == IsJMP) { jumptypelabel = "JMP"; }
|
||||
if (it.value() == IsBranch) { jumptypelabel = "Branch"; }
|
||||
if (it.value() == IsJSR) { jumptypelabel = "JSR"; }
|
||||
if (it.value() == IsBRA) { jumptypelabel = "BRA"; }
|
||||
//qDebug() << " Jump from" << uint16ToHex(it.key().first) << "to"
|
||||
// << uint16ToHex(it.key().second) << jumptypelabel;
|
||||
}
|
||||
}
|
||||
|
||||
JumpLines JumpLineManager::buildJumpLines()
|
||||
{
|
||||
//qDebug() << "A";
|
||||
|
||||
m_channelsAtAddress.clear();
|
||||
m_jumplines.m_maxChannel = 0;
|
||||
QMapIterator<TJump, JumpType> it(m_jumpmap);
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
TJump range = it.key();
|
||||
|
||||
JumpLine jl;
|
||||
jl.type = it.value();
|
||||
jl.from = range.first;
|
||||
jl.to = range.second;
|
||||
int channel = findBestChannel(jl);
|
||||
setChannelForJumpLine(channel,jl);
|
||||
|
||||
m_jumplines.jumpLines.append(jl);
|
||||
m_jumplines.m_maxChannel = qMax(m_jumplines.m_maxChannel, channel);
|
||||
}
|
||||
//qDebug() << "A";
|
||||
|
||||
|
||||
return m_jumplines;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int JumpLineManager::findBestChannel(JumpLine &jl)
|
||||
{
|
||||
//qDebug() << "findBestChannel()";
|
||||
if (m_jumplines.jumpLines.count() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int potentialChannel = 0;
|
||||
bool foundChannel = false;
|
||||
while (!foundChannel)
|
||||
{
|
||||
//qDebug() << "Tryning potential channel" << potentialChannel;
|
||||
bool matched = false;
|
||||
for (quint16 addr = jl.min(); addr <= jl.max(); addr++)
|
||||
{
|
||||
// If any of these addresses contain the potential channel, move on
|
||||
if (m_channelsAtAddress[addr].contains(potentialChannel))
|
||||
{
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
if (matched)
|
||||
{
|
||||
potentialChannel++;
|
||||
matched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
foundChannel = true;
|
||||
}
|
||||
}
|
||||
return potentialChannel;
|
||||
}
|
||||
|
||||
void JumpLineManager::setChannelForJumpLine(int channel, JumpLine &jl)
|
||||
{
|
||||
jl.channel = channel;
|
||||
for (quint16 addr = jl.min(); addr <= jl.max(); addr++)
|
||||
{
|
||||
m_channelsAtAddress[addr].append(channel);
|
||||
}
|
||||
}
|
||||
|
||||
void JumpLineManager::dumpJumpLines() const
|
||||
{
|
||||
//foreach (JumpLine jl, m_jumplines.jumpLines)
|
||||
// {
|
||||
//qDebug() << " JumpLine from:" << uint16ToHex(jl.from)
|
||||
// << " to:" << uint16ToHex(jl.to)
|
||||
// << "channel: " << jl.channel << " type:" << jl.type;
|
||||
// }
|
||||
}
|
||||
|
||||
bool JumpLineManager::doJumpsIntersect(TJump &A, TJump &B) const
|
||||
{
|
||||
|
||||
if (A == B) return false;
|
||||
if (isLineWithinRange(A.first,B) || isLineWithinRange(A.second,B))
|
||||
return true;
|
||||
|
||||
if (isLineWithinRange(B.first,A) || isLineWithinRange(B.second,A))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool JumpLineManager::isLineWithinRange(quint16 line, TJump &jm) const
|
||||
{
|
||||
quint16 min = qMin(jm.first,jm.second);
|
||||
quint16 max = qMax(jm.first,jm.second);
|
||||
|
||||
return (line > min && line < max);
|
||||
}
|
||||
|
||||
QList<JumpLine> JumpLines::jumpLinesAtAddress(quint16 addrs)
|
||||
{
|
||||
QList<JumpLine> list;
|
||||
foreach (JumpLine jl, jumpLines)
|
||||
{
|
||||
if (addrs >= jl.min() && addrs <= jl.max())
|
||||
{
|
||||
list.append(jl);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
@ -1,102 +1,102 @@
|
||||
#ifndef JUMPLINEMANAGER_H
|
||||
#define JUMPLINEMANAGER_H
|
||||
|
||||
#include <QPair>
|
||||
#include <QMap>
|
||||
#include <QMapIterator>
|
||||
#include <QDebug>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
typedef QPair<quint16,quint16> TJump;
|
||||
typedef enum {
|
||||
IsUnknownJump,
|
||||
IsJMP,
|
||||
IsBranch,
|
||||
IsJSR,
|
||||
IsBRA
|
||||
} JumpType;
|
||||
typedef QMap<TJump,JumpType> JumpMap;
|
||||
|
||||
class JumpLine {
|
||||
public:
|
||||
JumpLine() : from(0), to(0), channel(-1), type(IsUnknownJump) { }
|
||||
quint16 from;
|
||||
quint16 to;
|
||||
int channel;
|
||||
JumpType type;
|
||||
|
||||
inline quint16 min() const { return qMin(from,to); }
|
||||
inline quint16 max() const { return qMax(from,to); }
|
||||
inline bool isUp() const { return (from > to); }
|
||||
inline bool isDown() const { return !isUp(); }
|
||||
};
|
||||
|
||||
//////////////////
|
||||
|
||||
class JumpLines
|
||||
{
|
||||
public:
|
||||
JumpLines() : m_maxChannel(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QList<int> channelsAtAddress(quint16 address)
|
||||
{
|
||||
return m_channelsAtAddress[address];
|
||||
}
|
||||
|
||||
QList<JumpLine> jumpLinesAtAddress(quint16 addrs);
|
||||
|
||||
QList<JumpLine> jumpLines;
|
||||
|
||||
int m_maxChannel;
|
||||
|
||||
QMap<quint16, QList<int> > m_channelsAtAddress;
|
||||
};
|
||||
|
||||
//////////////////
|
||||
|
||||
class JumpLineManager
|
||||
{
|
||||
public:
|
||||
JumpLineManager(quint16 from = 0x0000, quint16 to = 0xffff);
|
||||
|
||||
void addJump(quint16 src, quint16 dest, JumpType type,quint16 from = 0, quint16 to = 0xffff);
|
||||
void dumpJumps() const;
|
||||
|
||||
JumpLines buildJumpLines();
|
||||
JumpLines getJumpLines() const { return m_jumplines; }
|
||||
|
||||
|
||||
|
||||
void clear() { m_jumpmap.clear(); }
|
||||
void dumpJumpLines() const;
|
||||
|
||||
int getNumJumpLineChannels() const { return m_jumplines.m_maxChannel; }
|
||||
|
||||
protected:
|
||||
int findBestChannel(JumpLine &jl);
|
||||
|
||||
void setChannelForJumpLine(int channel, JumpLine &jl);
|
||||
|
||||
private:
|
||||
quint16 m_start;
|
||||
quint16 m_end;
|
||||
|
||||
JumpMap m_jumpmap;
|
||||
|
||||
JumpLines m_jumplines;
|
||||
|
||||
QMap<quint16, QList<int>> m_channelsAtAddress;
|
||||
|
||||
|
||||
bool doJumpsIntersect(TJump &A, TJump &B) const;
|
||||
bool isLineWithinRange(quint16 line, TJump &jm) const;
|
||||
|
||||
void dumpJumps(JumpMap map) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // JUMPLINEMANAGER_H
|
||||
#ifndef JUMPLINEMANAGER_H
|
||||
#define JUMPLINEMANAGER_H
|
||||
|
||||
#include <QPair>
|
||||
#include <QMap>
|
||||
#include <QMapIterator>
|
||||
#include <QDebug>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
typedef QPair<quint16,quint16> TJump;
|
||||
typedef enum {
|
||||
IsUnknownJump,
|
||||
IsJMP,
|
||||
IsBranch,
|
||||
IsJSR,
|
||||
IsBRA
|
||||
} JumpType;
|
||||
typedef QMap<TJump,JumpType> JumpMap;
|
||||
|
||||
class JumpLine {
|
||||
public:
|
||||
JumpLine() : from(0), to(0), channel(-1), type(IsUnknownJump) { }
|
||||
quint16 from;
|
||||
quint16 to;
|
||||
int channel;
|
||||
JumpType type;
|
||||
|
||||
inline quint16 min() const { return qMin(from,to); }
|
||||
inline quint16 max() const { return qMax(from,to); }
|
||||
inline bool isUp() const { return (from > to); }
|
||||
inline bool isDown() const { return !isUp(); }
|
||||
};
|
||||
|
||||
//////////////////
|
||||
|
||||
class JumpLines
|
||||
{
|
||||
public:
|
||||
JumpLines() : m_maxChannel(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QList<int> channelsAtAddress(quint16 address)
|
||||
{
|
||||
return m_channelsAtAddress[address];
|
||||
}
|
||||
|
||||
QList<JumpLine> jumpLinesAtAddress(quint16 addrs);
|
||||
|
||||
QList<JumpLine> jumpLines;
|
||||
|
||||
int m_maxChannel;
|
||||
|
||||
QMap<quint16, QList<int> > m_channelsAtAddress;
|
||||
};
|
||||
|
||||
//////////////////
|
||||
|
||||
class JumpLineManager
|
||||
{
|
||||
public:
|
||||
JumpLineManager(quint16 from = 0x0000, quint16 to = 0xffff);
|
||||
|
||||
void addJump(quint16 src, quint16 dest, JumpType type,quint16 from = 0, quint16 to = 0xffff);
|
||||
void dumpJumps() const;
|
||||
|
||||
JumpLines buildJumpLines();
|
||||
JumpLines getJumpLines() const { return m_jumplines; }
|
||||
|
||||
|
||||
|
||||
void clear() { m_jumpmap.clear(); }
|
||||
void dumpJumpLines() const;
|
||||
|
||||
int getNumJumpLineChannels() const { return m_jumplines.m_maxChannel; }
|
||||
|
||||
protected:
|
||||
int findBestChannel(JumpLine &jl);
|
||||
|
||||
void setChannelForJumpLine(int channel, JumpLine &jl);
|
||||
|
||||
private:
|
||||
quint16 m_start;
|
||||
quint16 m_end;
|
||||
|
||||
JumpMap m_jumpmap;
|
||||
|
||||
JumpLines m_jumplines;
|
||||
|
||||
QMap<quint16, QList<int>> m_channelsAtAddress;
|
||||
|
||||
|
||||
bool doJumpsIntersect(TJump &A, TJump &B) const;
|
||||
bool isLineWithinRange(quint16 line, TJump &jm) const;
|
||||
|
||||
void dumpJumps(JumpMap map) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // JUMPLINEMANAGER_H
|
||||
|
@ -1,21 +1,21 @@
|
||||
#include "memory.h"
|
||||
#include <QDebug>
|
||||
|
||||
Memory::Memory()
|
||||
{
|
||||
quint8 zero = 0;
|
||||
for (int idx = 0; idx < 65536; idx++) {
|
||||
m_memory.append(zero);
|
||||
}
|
||||
}
|
||||
|
||||
bool Memory::addFile(QByteArray data, quint16 start)
|
||||
{
|
||||
if (start+data.length() > 65536) {
|
||||
qDebug() << "Memory overflow adding data."; return false;
|
||||
}
|
||||
|
||||
m_memory.replace(start,data.length(),data);
|
||||
|
||||
return true;
|
||||
}
|
||||
#include "memory.h"
|
||||
#include <QDebug>
|
||||
|
||||
Memory::Memory()
|
||||
{
|
||||
quint8 zero = 0;
|
||||
for (int idx = 0; idx < 65536; idx++) {
|
||||
m_memory.append(zero);
|
||||
}
|
||||
}
|
||||
|
||||
bool Memory::addFile(QByteArray data, quint16 start)
|
||||
{
|
||||
if (start+data.length() > 65536) {
|
||||
qDebug() << "Memory overflow adding data."; return false;
|
||||
}
|
||||
|
||||
m_memory.replace(start,data.length(),data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
class Memory {
|
||||
public:
|
||||
Memory();
|
||||
|
||||
bool addFile(QByteArray data, quint16 start);
|
||||
|
||||
QByteArray &values() { return m_memory; }
|
||||
|
||||
quint8 at(quint16 addr) { return m_memory.at(addr); }
|
||||
|
||||
private:
|
||||
QByteArray m_memory;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
class Memory {
|
||||
public:
|
||||
Memory();
|
||||
|
||||
bool addFile(QByteArray data, quint16 start);
|
||||
|
||||
QByteArray &values() { return m_memory; }
|
||||
|
||||
quint8 at(quint16 addr) { return m_memory.at(addr); }
|
||||
|
||||
private:
|
||||
QByteArray m_memory;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
60
src/main.cpp
60
src/main.cpp
@ -1,30 +1,30 @@
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
|
||||
#include "binaryfile.h"
|
||||
#include "genericfile.h"
|
||||
#include "diskfile.h"
|
||||
#include "catalogsector.h"
|
||||
#include "applesoftfile.h"
|
||||
#include "DiskExplorer.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
QCoreApplication::setOrganizationName("AppleSAWS");
|
||||
QCoreApplication::setOrganizationDomain("ml.com");
|
||||
QCoreApplication::setApplicationName("AppleSAWS");
|
||||
DiskExplorer w;
|
||||
QSettings settings;
|
||||
QString lastOpened = settings.value("lastOpened").toString();
|
||||
if (!lastOpened.isEmpty())
|
||||
{
|
||||
w.loadDiskFile(lastOpened);
|
||||
}
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
|
||||
}
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
|
||||
#include "binaryfile.h"
|
||||
#include "genericfile.h"
|
||||
#include "diskfile.h"
|
||||
#include "catalogsector.h"
|
||||
#include "applesoftfile.h"
|
||||
#include "DiskExplorer.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
QCoreApplication::setOrganizationName("LydianScaleSoftware");
|
||||
QCoreApplication::setOrganizationDomain("lydianscale.com");
|
||||
QCoreApplication::setApplicationName("AppleSAWS");
|
||||
DiskExplorer w;
|
||||
QSettings settings;
|
||||
QString lastOpened = settings.value("lastOpened").toString();
|
||||
if (!lastOpened.isEmpty())
|
||||
{
|
||||
w.loadDiskFile(lastOpened);
|
||||
}
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,100 +1,100 @@
|
||||
#include <QDebug>
|
||||
#include "relocatablefile.h"
|
||||
#include "util.h"
|
||||
|
||||
RelocatableFile::RelocatableFile(QByteArray data) : GenericFile(data)
|
||||
{
|
||||
// qDebug() << "Relocatable file ctor";
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
void RelocatableFile::setData(QByteArray data)
|
||||
{
|
||||
// qDebug() << "setData()";
|
||||
if (data.length() >= 6) {
|
||||
m_starting_ram_address = makeWord(m_data[0],m_data[1]);
|
||||
m_ram_image_length = makeWord(m_data[2],m_data[3]);
|
||||
m_code_image_length = makeWord(m_data[4],m_data[5]);
|
||||
|
||||
int offset = 0;
|
||||
|
||||
for (int idx = 6; idx < m_code_image_length+6; idx++) {
|
||||
quint8 val = m_data[idx];
|
||||
m_binary_code_image.append(val);
|
||||
}
|
||||
|
||||
for (int N = 0; N < (m_code_image_length/4); N++) {
|
||||
offset = m_code_image_length+ 6 +(N*4);
|
||||
|
||||
// qDebug() << "N: " << N << uint8ToHex(m_data[offset])
|
||||
// << uint8ToHex(m_data[offset+1])
|
||||
// << uint8ToHex(m_data[offset+2])
|
||||
// << uint8ToHex(m_data[offset+3]);
|
||||
|
||||
RelocatableDictItem rdi = RelocatableDictItem(m_data[offset],m_data[offset+1],
|
||||
m_data[offset+2],m_data[offset+3]);
|
||||
m_relocatable_dict.append(rdi);
|
||||
if (rdi.isEndOfRLD()) { break; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void RelocatableFile::dump()
|
||||
{
|
||||
qDebug() << "\nTotalLength: " << length();
|
||||
qDebug() << "Starting Ram Address: " << (quint16) m_starting_ram_address << uint16ToHex(m_starting_ram_address);
|
||||
qDebug() << "Length of Ram Image: " << (quint16) m_ram_image_length << uint16ToHex(m_ram_image_length);
|
||||
qDebug() << "Length of Code Image: " << (quint16) m_code_image_length << uint16ToHex(m_code_image_length);
|
||||
|
||||
int itemIdx = 0;
|
||||
foreach (RelocatableDictItem item, m_relocatable_dict) {
|
||||
Byte4ReturnType b4rt = item.getByte4();
|
||||
QString typestr;
|
||||
if (b4rt.first == ESDSymbol) { typestr = "ESDSymbol"; }
|
||||
else if (b4rt.first == ByteHi) { typestr = "Hi Byte"; }
|
||||
else { typestr = "Lo Byte"; }
|
||||
quint16 fo = item.getFieldOffset();
|
||||
qDebug() << " Item #" << itemIdx++
|
||||
<< "Field Offset: " << uint16ToHex(fo)
|
||||
<< "FieldSize: " << ((item.getFieldSize()==RFS2Byte)?"2-Byte":"1-Byte")
|
||||
<< typestr << uint8ToHex(b4rt.second)
|
||||
<< ((item.isNotEndOfRLD())?"NotEndOfRLD":"EndOfRLD")
|
||||
<< " " << ((item.isExtern())?"Extern":"Not Extern");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
QStringList RelocatableFile::decodeRelocatableDict()
|
||||
{
|
||||
QStringList retval;
|
||||
int idx = 0;
|
||||
foreach (RelocatableDictItem item, m_relocatable_dict) {
|
||||
Byte4ReturnType b4rt = item.getByte4();
|
||||
QString typestr;
|
||||
if (b4rt.first == ESDSymbol) { typestr = "ESDSymbol"; }
|
||||
else if (b4rt.first == ByteHi) { typestr = "Hi Byte"; }
|
||||
else { typestr = "Lo Byte"; }
|
||||
quint16 fo = item.getFieldOffset();
|
||||
// qDebug() << " Item #" << idx
|
||||
// << "Field Offset: " << uint16ToHex(fo)
|
||||
// << "FieldSize: " << ((item.getFieldSize()==RFS2Byte)?"2-Byte":"1-Byte")
|
||||
// << typestr << uint8ToHex(b4rt.second)
|
||||
// << ((item.isNotEndOfRLD())?"NotEndOfRLD":"EndOfRLD")
|
||||
// << " " << ((item.isExtern())?"Extern":"Not Extern");
|
||||
|
||||
retval.append(QString("Item %1, Offset %2, @ %3, %4 Field, %5")
|
||||
.arg(idx++)
|
||||
.arg(uint16ToHex(fo))
|
||||
.arg(uint16ToHex(fo+address()+6))
|
||||
.arg((item.getFieldSize()==RFS2Byte)?"2-Byte":"1-Byte")
|
||||
.arg((item.isExtern())?"Extern":"Not Extern"));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
#include <QDebug>
|
||||
#include "relocatablefile.h"
|
||||
#include "util.h"
|
||||
|
||||
RelocatableFile::RelocatableFile(QByteArray data) : GenericFile(data)
|
||||
{
|
||||
// qDebug() << "Relocatable file ctor";
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
void RelocatableFile::setData(QByteArray data)
|
||||
{
|
||||
// qDebug() << "setData()";
|
||||
if (data.length() >= 6) {
|
||||
m_starting_ram_address = makeWord(m_data[0],m_data[1]);
|
||||
m_ram_image_length = makeWord(m_data[2],m_data[3]);
|
||||
m_code_image_length = makeWord(m_data[4],m_data[5]);
|
||||
|
||||
int offset = 0;
|
||||
|
||||
for (int idx = 6; idx < m_code_image_length+6; idx++) {
|
||||
quint8 val = m_data[idx];
|
||||
m_binary_code_image.append(val);
|
||||
}
|
||||
|
||||
for (int N = 0; N < (m_code_image_length/4); N++) {
|
||||
offset = m_code_image_length+ 6 +(N*4);
|
||||
|
||||
// qDebug() << "N: " << N << uint8ToHex(m_data[offset])
|
||||
// << uint8ToHex(m_data[offset+1])
|
||||
// << uint8ToHex(m_data[offset+2])
|
||||
// << uint8ToHex(m_data[offset+3]);
|
||||
|
||||
RelocatableDictItem rdi = RelocatableDictItem(m_data[offset],m_data[offset+1],
|
||||
m_data[offset+2],m_data[offset+3]);
|
||||
m_relocatable_dict.append(rdi);
|
||||
if (rdi.isEndOfRLD()) { break; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void RelocatableFile::dump()
|
||||
{
|
||||
qDebug() << "\nTotalLength: " << length();
|
||||
qDebug() << "Starting Ram Address: " << (quint16) m_starting_ram_address << uint16ToHex(m_starting_ram_address);
|
||||
qDebug() << "Length of Ram Image: " << (quint16) m_ram_image_length << uint16ToHex(m_ram_image_length);
|
||||
qDebug() << "Length of Code Image: " << (quint16) m_code_image_length << uint16ToHex(m_code_image_length);
|
||||
|
||||
int itemIdx = 0;
|
||||
foreach (RelocatableDictItem item, m_relocatable_dict) {
|
||||
Byte4ReturnType b4rt = item.getByte4();
|
||||
QString typestr;
|
||||
if (b4rt.first == ESDSymbol) { typestr = "ESDSymbol"; }
|
||||
else if (b4rt.first == ByteHi) { typestr = "Hi Byte"; }
|
||||
else { typestr = "Lo Byte"; }
|
||||
quint16 fo = item.getFieldOffset();
|
||||
qDebug() << " Item #" << itemIdx++
|
||||
<< "Field Offset: " << uint16ToHex(fo)
|
||||
<< "FieldSize: " << ((item.getFieldSize()==RFS2Byte)?"2-Byte":"1-Byte")
|
||||
<< typestr << uint8ToHex(b4rt.second)
|
||||
<< ((item.isNotEndOfRLD())?"NotEndOfRLD":"EndOfRLD")
|
||||
<< " " << ((item.isExtern())?"Extern":"Not Extern");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
QStringList RelocatableFile::decodeRelocatableDict()
|
||||
{
|
||||
QStringList retval;
|
||||
int idx = 0;
|
||||
foreach (RelocatableDictItem item, m_relocatable_dict) {
|
||||
Byte4ReturnType b4rt = item.getByte4();
|
||||
QString typestr;
|
||||
if (b4rt.first == ESDSymbol) { typestr = "ESDSymbol"; }
|
||||
else if (b4rt.first == ByteHi) { typestr = "Hi Byte"; }
|
||||
else { typestr = "Lo Byte"; }
|
||||
quint16 fo = item.getFieldOffset();
|
||||
// qDebug() << " Item #" << idx
|
||||
// << "Field Offset: " << uint16ToHex(fo)
|
||||
// << "FieldSize: " << ((item.getFieldSize()==RFS2Byte)?"2-Byte":"1-Byte")
|
||||
// << typestr << uint8ToHex(b4rt.second)
|
||||
// << ((item.isNotEndOfRLD())?"NotEndOfRLD":"EndOfRLD")
|
||||
// << " " << ((item.isExtern())?"Extern":"Not Extern");
|
||||
|
||||
retval.append(QString("Item %1, Offset %2, @ %3, %4 Field, %5")
|
||||
.arg(idx++)
|
||||
.arg(uint16ToHex(fo))
|
||||
.arg(uint16ToHex(fo+address()+6))
|
||||
.arg((item.getFieldSize()==RFS2Byte)?"2-Byte":"1-Byte")
|
||||
.arg((item.isExtern())?"Extern":"Not Extern"));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1,109 +1,109 @@
|
||||
#ifndef RELOCATABLEFILE_H
|
||||
#define RELOCATABLEFILE_H
|
||||
|
||||
#include <QPair>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "genericfile.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
typedef enum { RFS1Byte, RFS2Byte } FieldSize;
|
||||
typedef enum { ULIsHighByte, ULIsLowByte } WordUpperLower;
|
||||
typedef enum { LowHi, HiLow } Endianness;
|
||||
typedef enum { ByteLo, ByteHi, ESDSymbol } Byte4Type;
|
||||
|
||||
typedef QPair<Byte4Type, quint8> Byte4ReturnType;
|
||||
|
||||
class RelocatableDictItem {
|
||||
public:
|
||||
RelocatableDictItem() {init(0,0,0,0); }
|
||||
RelocatableDictItem(quint8 rld, quint8 fo_low, quint8 fo_hi, quint8 lbsym) {
|
||||
init(rld,fo_low, fo_hi,lbsym);
|
||||
}
|
||||
RelocatableDictItem(quint8 rld, quint16 fo, quint8 lbsym) {
|
||||
init(rld,fo,lbsym);
|
||||
}
|
||||
|
||||
void init(quint8 rld, quint8 fo_low, quint8 fo_hi, quint8 lbsym) {
|
||||
m_rld_flag = rld;
|
||||
m_halfword_or_sym_num = lbsym;
|
||||
m_field_offset = makeWord(fo_low,fo_hi);
|
||||
}
|
||||
|
||||
void init(quint8 rld, quint16 fo, quint8 lbsym) {
|
||||
m_rld_flag = rld;
|
||||
m_halfword_or_sym_num = lbsym;
|
||||
m_field_offset = fo;
|
||||
}
|
||||
|
||||
FieldSize getFieldSize() { return (m_rld_flag & 0x80)?RFS2Byte:RFS1Byte; }
|
||||
WordUpperLower getWordBytePos() { return (m_rld_flag & 0x40)?ULIsHighByte:ULIsLowByte; }
|
||||
Endianness getEndianness() { return (m_rld_flag & 0x20)?HiLow:LowHi; }
|
||||
bool isExtern() { return (m_rld_flag & 0x10); }
|
||||
bool isNotEndOfRLD() { return (m_rld_flag & 0x01); }
|
||||
bool isEndOfRLD() { return !(m_rld_flag & 0x01); }
|
||||
|
||||
Byte4ReturnType getByte4() {
|
||||
Byte4ReturnType retval;
|
||||
|
||||
if (isExtern()) {
|
||||
retval.first = ESDSymbol;
|
||||
} else if (getWordBytePos() == ULIsHighByte) {
|
||||
retval.first = ByteHi;
|
||||
} else {
|
||||
retval.first = ByteLo;
|
||||
}
|
||||
|
||||
retval.second = m_halfword_or_sym_num;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
quint16 getFieldOffset() { return m_field_offset; }
|
||||
|
||||
quint8 getRLDFlag() { return m_rld_flag; }
|
||||
quint8 getRawHalfWordOrSymNum() { return m_halfword_or_sym_num; }
|
||||
|
||||
private:
|
||||
|
||||
quint8 m_rld_flag;
|
||||
quint16 m_field_offset;
|
||||
quint8 m_halfword_or_sym_num;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class RelocatableFile : public GenericFile
|
||||
{
|
||||
public:
|
||||
|
||||
RelocatableFile(QByteArray data |