42 | * The conversion reuses largely Dwarf floppy code: the DMK image is 43 | * loaded through the implementation for DMK legacy floppies, the 44 | * {@code DiskConverter} simply subclassing that class for writing 45 | * the IMD file (named after the original file with the ".imd" extension) 46 | * directly in the constructor. 47 | *
48 | * 49 | * @author Dr. Hans-Walter Latz / Berlin (2018) 50 | */ 51 | public class CnvDmk2Imd extends DMKFloppyDisk { 52 | 53 | private boolean doLog = false; // prevent logging the DMK reading 54 | 55 | public CnvDmk2Imd(File dmkFile, File imdFile) throws IOException { 56 | super(dmkFile); 57 | 58 | /* 59 | * create the IMD from the DMK sectors and disk characteristics 60 | */ 61 | 62 | // re-enable logging for issuing the disk characteristics 63 | this.doLog = true; 64 | 65 | // write the imd file from the sectors found in the dmk file 66 | logf("# Cyl0Sectors = %s sectors\n", this.cyl0Sectors); // track 0 and 1 67 | logf("# DataSectors = %s sectors\n", this.dataSectors); 68 | logf("# cylinders = %d\n", this.cylinders); 69 | 70 | int expectedSectorCount = ((this.cylinders - 1) * this.dataSectors * 2) + (this.cyl0Sectors * 2); 71 | logf("# expectedSectors = %d ?=? this.sectors.length = %d\n", expectedSectorCount, this.sectors.size()); 72 | 73 | try (OutputStream imd = new BufferedOutputStream(new FileOutputStream(imdFile))) { 74 | // write the human readable header 75 | imd.write("IMD converted from DMK".getBytes()); 76 | imd.write(0x1A); // EOF is end marker for the header 77 | 78 | // which sector loaded from the DMK to write next to IMD 79 | int sectorStartIndex = 0; 80 | 81 | // write track 0 (cyl 0, head 0): 128 bytes sector length (sectInfo = 0), mode = 2 (experimental) 82 | sectorStartIndex = this.writeTrack(imd, 2, 0, 0, this.cyl0Sectors, 0, sectorStartIndex); 83 | 84 | // write track 1 (cyl 0, head 1): 256 bytes per sector, mode = 5 from here (experimental) 85 | sectorStartIndex = this.writeTrack(imd, 5, 0, 1, this.cyl0Sectors, 1, sectorStartIndex); 86 | 87 | // write the other sectors 88 | int cyl = 1; 89 | int head = 0; 90 | while(cyl < this.cylinders) { 91 | sectorStartIndex = this.writeTrack(imd, 5, cyl, head, this.dataSectors, 2, sectorStartIndex); 92 | head++; 93 | if (head > 1) { 94 | head = 0; 95 | cyl++; 96 | } 97 | } 98 | } 99 | } 100 | 101 | private int writeTrack(OutputStream imd, int mode, int cylNo, int headNo, int numSects, int sectInfo, int sectorStartIndex) throws IOException { 102 | // track header 103 | imd.write(mode); 104 | imd.write(cylNo); 105 | imd.write(headNo & 0x3F); 106 | imd.write(numSects); 107 | imd.write(sectInfo); 108 | 109 | // sector numbering map (Xerox floppies have linear ascending sector ordering, as seens so far...) 110 | for (int i = 0; i < numSects; i++) { 111 | imd.write(i + 1); 112 | } 113 | 114 | // no sectorCylinder map present, as we write (headNo & 0x80) == 0 115 | 116 | // no sectorHead map present, as we write (headNo & 0x40) == 0 117 | 118 | // write sectors 119 | for (int i = 0; i < numSects; i++) { 120 | this.writeSectorContent(imd, this.sectors.get(sectorStartIndex + i)); 121 | } 122 | 123 | // done with this track 124 | return sectorStartIndex + numSects; 125 | } 126 | 127 | private void writeSectorContent(OutputStream imd, short[] sector) throws IOException { 128 | // sector content type: full content, no filling with constant byte or 0 129 | imd.write(1); 130 | 131 | // sector bytes 132 | for (int i = 0; i < sector.length; i++) { 133 | int word = sector[i]; 134 | int upperByte = (word >> 8) & 0x00FF; 135 | int lowerByte = word & 0x00FF; 136 | imd.write(upperByte); 137 | imd.write(lowerByte); 138 | } 139 | } 140 | 141 | protected void logf(String template, Object... args) { 142 | if (this.doLog) { 143 | System.out.printf(template, args); 144 | } 145 | } 146 | 147 | public static void main(String[] args) throws IOException { 148 | if (args.length < 1) { 149 | System.err.printf("missing DMK filename parameter\n"); 150 | return; 151 | } 152 | 153 | File dmkFile = new File(args[0]); 154 | File imdFile = new File(args[0] + ".imd"); 155 | new CnvDmk2Imd(dmkFile, imdFile); 156 | 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/DwarfMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2020, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine; 28 | 29 | import java.io.IOException; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | /** 34 | * Main program for the Dwarf Mesa emulator family, dispatching to 35 | * either the Guam machine emulation (Duchess) or the 6085/daybreak 36 | * emulation (Draco), depending on the machine type selection argument 37 | * and passing the remaining command line arguments to the invoked 38 | * emulation program. 39 | * 40 | * @author Dr. Hans-Walter Latz / Berlin (2020) 41 | */ 42 | public class DwarfMain { 43 | 44 | private static void usage() { 45 | System.out.println("Usage: Dwarf -duchess|-draco46 | * Furthermore, the MP code 0915 is intercepted by default and halts 47 | * the mesa engine, as no networking is currently available, so no 48 | * remote debugger can connect to this machine (if an XDE with a debugger 49 | * should ever be available...). 50 | *
51 | * 52 | * @author Dr. Hans-Walter Latz / Berlin (2017) 53 | */ 54 | public class DebuggerSubstituteMpHandler implements MPHandler { 55 | 56 | // intercept MP code 0915 (waiting for remote debugger to connect)? 57 | private final boolean stopOn0915; 58 | 59 | /** 60 | * Constructor with parametrization for MP 915. 61 | * 62 | * @param stopOn0915 should a MP 0915 stop the mesa engine? 63 | */ 64 | public DebuggerSubstituteMpHandler(boolean stopOn0915) { 65 | this.stopOn0915 = stopOn0915; 66 | } 67 | 68 | /** 69 | * Default constructor, activating MP 0915 interception. 70 | */ 71 | public DebuggerSubstituteMpHandler() { 72 | this(true); 73 | } 74 | 75 | // did we see the characteristic debugger substitue MP code? 76 | private boolean inDebuggerSubstitute = false; 77 | 78 | // the list of the substitutes MP codes seen so far 79 | private List38 | * The basic functionality for the Dwarf UI is inherited from the parent 39 | * class {@code DisplayPane}. 40 | *
41 | * 42 | * @author Dr. Hans-Walter Latz / Berlin (2020) 43 | */ 44 | public class Display8BitColorPane extends DisplayPane { 45 | 46 | private static final long serialVersionUID = 1679737299827954144L; 47 | 48 | // number of pixels in a memory page: 49 | // with 8-bit color display data having 2 pixels per mesa word 50 | private static final int PIXELS_PER_PAGE = PrincOpsDefs.WORDS_PER_PAGE * 2; 51 | 52 | // Pilot/BWS does have "line breaks" in a display page for 8-bit colors, 53 | // so a scanline is a multiple of pages => multiple of 512 pixels 54 | private static int getEffectiveWidth(int displayWidth) { 55 | return ((displayWidth + PIXELS_PER_PAGE - 1) / PIXELS_PER_PAGE) * PIXELS_PER_PAGE; 56 | } 57 | 58 | public Display8BitColorPane(int displayWidth, int displayHeight) { 59 | super(getEffectiveWidth(displayWidth), displayHeight); 60 | } 61 | 62 | @Override 63 | protected BufferedImage createBackingImage(int displayWidth, int displayHeight) { 64 | return new BufferedImage(displayWidth, displayHeight, BufferedImage.TYPE_INT_RGB); 65 | } 66 | 67 | @Override 68 | public boolean copyDisplayContent(short[] mem, int start, int count, short[] pageFlags, int firstPage, int[] colorTable) { 69 | DataBufferInt dbb = (DataBufferInt)bi.getRaster().getDataBuffer(); 70 | int[] pixels = dbb.getData(); 71 | 72 | boolean bitmapWasUpdated = false; 73 | int end = start + Math.min(Math.min(count, pixels.length / 2), mem.length - start); 74 | int bitmapIdx = 0; 75 | int memIdx = start; 76 | int pageIdx = firstPage; 77 | int pageCount = (count + PrincOpsDefs.WORDS_PER_PAGE - 1) / PrincOpsDefs.WORDS_PER_PAGE; 78 | while (pageCount-- > 0) { 79 | short flags = pageFlags[pageIdx++]; 80 | if ((flags & PrincOpsDefs.MAPFLAGS_DIRTY) == 0) { 81 | memIdx += PrincOpsDefs.WORDS_PER_PAGE; 82 | bitmapIdx += PrincOpsDefs.WORDS_PER_PAGE * 2; // 2 pixels per mesa word in display data 83 | continue; 84 | } 85 | for (int i = 0; i < PrincOpsDefs.WORDS_PER_PAGE && memIdx < end; i++) { 86 | int w = mem[memIdx++] & 0xFFFF; 87 | pixels[bitmapIdx++] = colorTable[w >>> 8]; 88 | pixels[bitmapIdx++] = colorTable[w & 0x00FF]; 89 | } 90 | bitmapWasUpdated = true; 91 | } 92 | 93 | return bitmapWasUpdated; 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/dwarf/DisplayMonochromePane.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017,2020, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.dwarf; 28 | 29 | import java.awt.image.BufferedImage; 30 | import java.awt.image.DataBufferByte; 31 | 32 | import dev.hawala.dmachine.engine.PrincOpsDefs; 33 | 34 | /** 35 | * Java swing pane representing the screen of a Dwarf machine, providing 36 | * a Black&White display. 37 | *38 | * The basic functionality for the Dwarf UI is inherited from the parent 39 | * class {@code DisplayPane}. 40 | *
41 | * 42 | * @author Dr. Hans-Walter Latz / Berlin (2017,2020) 43 | */ 44 | public class DisplayMonochromePane extends DisplayPane { 45 | 46 | private static final long serialVersionUID = 7037553149132148980L; 47 | 48 | public DisplayMonochromePane(int displayWidth, int displayHeight) { 49 | super(displayWidth, displayHeight); 50 | } 51 | 52 | @Override 53 | protected BufferedImage createBackingImage(int displayWidth, int displayHeight) { 54 | return new BufferedImage(displayWidth, displayHeight, BufferedImage.TYPE_BYTE_BINARY); 55 | } 56 | 57 | @Override 58 | public boolean copyDisplayContent(short[] mem, int start, int count, short[] pageFlags, int firstPage, int[] colorTable) { 59 | DataBufferByte dbb = (DataBufferByte)bi.getRaster().getDataBuffer(); 60 | byte[] data = dbb.getData(); 61 | 62 | boolean bitmapWasUpdated = false; 63 | int end = start + Math.min(Math.min(count, data.length / 2), mem.length - start); 64 | int bitmapIdx = 0; 65 | int memIdx = start; 66 | int pageIdx = firstPage; 67 | int pageCount = (count + PrincOpsDefs.WORDS_PER_PAGE - 1) / PrincOpsDefs.WORDS_PER_PAGE; 68 | while (pageCount-- > 0) { 69 | short flags = pageFlags[pageIdx++]; 70 | if ((flags & PrincOpsDefs.MAPFLAGS_DIRTY) == 0) { 71 | memIdx += PrincOpsDefs.WORDS_PER_PAGE; 72 | bitmapIdx += PrincOpsDefs.WORDS_PER_PAGE * 2; 73 | continue; 74 | } 75 | for (int i = 0; i < PrincOpsDefs.WORDS_PER_PAGE && memIdx < end; i++) { 76 | short w = (short)(mem[memIdx++] ^ 0xFFFF); // TODO: really invert manually ?? 77 | data[bitmapIdx++] = (byte)((w >>> 8)); 78 | data[bitmapIdx++] = (byte)((w & 0x00FF)); 79 | } 80 | bitmapWasUpdated = true; 81 | } 82 | 83 | return bitmapWasUpdated; 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/dwarf/KeyHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.dwarf; 28 | 29 | import java.awt.event.KeyEvent; 30 | import java.awt.event.KeyListener; 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | import java.util.concurrent.ExecutorService; 34 | import java.util.concurrent.Executors; 35 | 36 | import dev.hawala.dmachine.engine.Config; 37 | import dev.hawala.dmachine.engine.Processes; 38 | 39 | /** 40 | * Key stroke listener for the Dwarf screen pane, forwarding the key-pressed and 41 | * key-released event to the keyboard-mapper. 42 | *
43 | * Handling diacritical start characters (also called dead keys, for example the
44 | * accent-grave (forward-tick), accent-aigue (back-tick), accent-circonflex (^) etc.)
45 | * is a problem under Linux, as modern Linuces think to be smart in prehandling those
46 | * characters to combine them with the next pressed key: this has the net effect
47 | * that for a press-release cycle, only the release event arrives in the Java window
48 | * key listener (using the focus management listening alternative does not help,
49 | * as even being a level deeper in the event pipeline did not help).
50 | *
51 | * This is handled here in a questionable, but seemingly working way: if a key-release
52 | * event arrives for which the key-pressed is missing, first a synthetic key-pressed
53 | * event is sent to the keyboard-mapper, and the key-release event is delayed by 50 msecs.
54 | *
40 | * The main purpose is to handle closing the main window while 41 | * the mesa engine is running: a confirmation dialog is showed and 42 | * if closing is confirmed, the mesa engine is halted gracefully 43 | * by shutting down the devices, which saves buffered data of 44 | * the harddisk resp. the currently loaded floppy disk. 45 | *
46 | *47 | * Additionally refreshing of the Java UI is paused if the application 48 | * is iconized. 49 | *
50 | * 51 | * @author Dr. Hans-Walter Latz / Berlin (2017) 52 | */ 53 | public class WindowStateListener implements WindowListener { 54 | 55 | private final MainUI mainWindow; 56 | private final UiRefresher uiRefresher; 57 | private final BooleanSupplier runningIndicator; 58 | private final Runnable windowCloser; 59 | 60 | /** 61 | * Constructor. 62 | * 63 | * @param mainWindow the main window of the Dwarf application 64 | * @param uiRefresher the ui refresher handling the Java ui updates 65 | * @param runningIndicator function indicating if the emulator engine is currently running 66 | * @param windowCloser function for allowing to close the main window when the engine finally stops 67 | */ 68 | public WindowStateListener(MainUI mainWindow, UiRefresher uiRefresher, BooleanSupplier runningIndicator, Runnable windowCloser) { 69 | this.mainWindow = mainWindow; 70 | this.uiRefresher = uiRefresher; 71 | this.runningIndicator = runningIndicator; 72 | this.windowCloser = windowCloser; 73 | } 74 | 75 | @Override 76 | public void windowOpened(WindowEvent e) { } 77 | 78 | @Override 79 | public void windowClosing(WindowEvent e) { 80 | // check if the mesa engine is running and handle accordingly 81 | if (!this.runningIndicator.getAsBoolean()) { 82 | // simply terminate the program 83 | System.exit(0); 84 | } 85 | 86 | // the mesa engine is running, so ask what to do 87 | int result = JOptionPane.showConfirmDialog( 88 | this.mainWindow.getFrame(), 89 | "OK to close window and shutdown the running mesa engine?", 90 | "Dwarf: Mesa Engine is currently running", 91 | JOptionPane.YES_NO_OPTION); 92 | if (result == JOptionPane.YES_OPTION) { 93 | // halt the engine, let Agent states be saved and let the program be stopped 94 | Processes.requestMesaEngineStop(); // this stops the engine and lets the mesa engine thread shut down the agents 95 | this.windowCloser.run(); // this closes the main window when the mesa engine thread is done 96 | } 97 | } 98 | 99 | @Override 100 | public void windowClosed(WindowEvent e) { } 101 | 102 | @Override 103 | public void windowIconified(WindowEvent e) { 104 | this.uiRefresher.setDoRefreshUi(false); 105 | } 106 | 107 | @Override 108 | public void windowDeiconified(WindowEvent e) { 109 | this.uiRefresher.setDoRefreshUi(true); 110 | } 111 | 112 | @Override 113 | public void windowActivated(WindowEvent e) { } 114 | 115 | @Override 116 | public void windowDeactivated(WindowEvent e) { } 117 | 118 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/dwarf/eKeyEventCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.dwarf; 28 | 29 | /** 30 | * Enumeration of the keyboard key names in Java, as defined as constants 31 | * in the class {@code KeyEvent}, with the corresppnding extended key code.. 32 | * 33 | * @author Dr. Hans-Walter Latz / Berlin (2017) 34 | */ 35 | public enum eKeyEventCode { 36 | VK_0(48), 37 | VK_1(49), 38 | VK_2(50), 39 | VK_3(51), 40 | VK_4(52), 41 | VK_5(53), 42 | VK_6(54), 43 | VK_7(55), 44 | VK_8(56), 45 | VK_9(57), 46 | VK_A(65), 47 | VK_ACCEPT(30), 48 | VK_ADD(107), 49 | VK_AGAIN(65481), 50 | VK_ALL_CANDIDATES(256), 51 | VK_ALPHANUMERIC(240), 52 | VK_ALT(18), 53 | VK_ALT_GRAPH(65406), 54 | VK_AMPERSAND(150), 55 | VK_ASTERISK(151), 56 | VK_AT(512), 57 | VK_B(66), 58 | VK_BACK_QUOTE(192), 59 | VK_BACK_SLASH(92), 60 | VK_BACK_SPACE(8), 61 | VK_BEGIN(65368), 62 | VK_BRACELEFT(161), 63 | VK_BRACERIGHT(162), 64 | VK_C(67), 65 | VK_CANCEL(3), 66 | VK_CAPS_LOCK(20), 67 | VK_CIRCUMFLEX(514), 68 | VK_CLEAR(12), 69 | VK_CLOSE_BRACKET(93), 70 | VK_CODE_INPUT(258), 71 | VK_COLON(513), 72 | VK_COMMA(44), 73 | VK_COMPOSE(65312), 74 | VK_CONTEXT_MENU(525), 75 | VK_CONTROL(17), 76 | VK_CONVERT(28), 77 | VK_COPY(65485), 78 | VK_CUT(65489), 79 | VK_D(68), 80 | VK_DEAD_ABOVEDOT(134), 81 | VK_DEAD_ABOVERING(136), 82 | VK_DEAD_ACUTE(129), 83 | VK_DEAD_BREVE(133), 84 | VK_DEAD_CARON(138), 85 | VK_DEAD_CEDILLA(139), 86 | VK_DEAD_CIRCUMFLEX(130), 87 | VK_DEAD_DIAERESIS(135), 88 | VK_DEAD_DOUBLEACUTE(137), 89 | VK_DEAD_GRAVE(128), 90 | VK_DEAD_IOTA(141), 91 | VK_DEAD_MACRON(132), 92 | VK_DEAD_OGONEK(140), 93 | VK_DEAD_SEMIVOICED_SOUND(143), 94 | VK_DEAD_TILDE(131), 95 | VK_DEAD_VOICED_SOUND(142), 96 | VK_DECIMAL(110), 97 | VK_DELETE(127), 98 | VK_DIVIDE(111), 99 | VK_DOLLAR(515), 100 | VK_DOWN(40), 101 | VK_E(69), 102 | VK_END(35), 103 | VK_ENTER(10), 104 | VK_EQUALS(61), 105 | VK_ESCAPE(27), 106 | VK_EURO_SIGN(516), 107 | VK_EXCLAMATION_MARK(517), 108 | VK_F(70), 109 | VK_F1(112), 110 | VK_F10(121), 111 | VK_F11(122), 112 | VK_F12(123), 113 | VK_F13(61440), 114 | VK_F14(61441), 115 | VK_F15(61442), 116 | VK_F16(61443), 117 | VK_F17(61444), 118 | VK_F18(61445), 119 | VK_F19(61446), 120 | VK_F2(113), 121 | VK_F20(61447), 122 | VK_F21(61448), 123 | VK_F22(61449), 124 | VK_F23(61450), 125 | VK_F24(61451), 126 | VK_F3(114), 127 | VK_F4(115), 128 | VK_F5(116), 129 | VK_F6(117), 130 | VK_F7(118), 131 | VK_F8(119), 132 | VK_F9(120), 133 | VK_FINAL(24), 134 | VK_FIND(65488), 135 | VK_FULL_WIDTH(243), 136 | VK_G(71), 137 | VK_GREATER(160), 138 | VK_H(72), 139 | VK_HALF_WIDTH(244), 140 | VK_HELP(156), 141 | VK_HIRAGANA(242), 142 | VK_HOME(36), 143 | VK_I(73), 144 | VK_INPUT_METHOD_ON_OFF(263), 145 | VK_INSERT(155), 146 | VK_INVERTED_EXCLAMATION_MARK(518), 147 | VK_J(74), 148 | VK_JAPANESE_HIRAGANA(260), 149 | VK_JAPANESE_KATAKANA(259), 150 | VK_JAPANESE_ROMAN(261), 151 | VK_K(75), 152 | VK_KANA(21), 153 | VK_KANA_LOCK(262), 154 | VK_KANJI(25), 155 | VK_KATAKANA(241), 156 | VK_KP_DOWN(225), 157 | VK_KP_LEFT(226), 158 | VK_KP_RIGHT(227), 159 | VK_KP_UP(224), 160 | VK_L(76), 161 | VK_LEFT(37), 162 | VK_LEFT_PARENTHESIS(519), 163 | VK_LESS(153), 164 | VK_M(77), 165 | VK_META(157), 166 | VK_MINUS(45), 167 | VK_MODECHANGE(31), 168 | VK_MULTIPLY(106), 169 | VK_N(78), 170 | VK_NONCONVERT(29), 171 | VK_NUM_LOCK(144), 172 | VK_NUMBER_SIGN(520), 173 | VK_NUMPAD0(96), 174 | VK_NUMPAD1(97), 175 | VK_NUMPAD2(98), 176 | VK_NUMPAD3(99), 177 | VK_NUMPAD4(100), 178 | VK_NUMPAD5(101), 179 | VK_NUMPAD6(102), 180 | VK_NUMPAD7(103), 181 | VK_NUMPAD8(104), 182 | VK_NUMPAD9(105), 183 | VK_O(79), 184 | VK_OPEN_BRACKET(91), 185 | VK_P(80), 186 | VK_PAGE_DOWN(34), 187 | VK_PAGE_UP(33), 188 | VK_PASTE(65487), 189 | VK_PAUSE(19), 190 | VK_PERIOD(46), 191 | VK_PLUS(521), 192 | VK_PREVIOUS_CANDIDATE(257), 193 | VK_PRINTSCREEN(154), 194 | VK_PROPS(65482), 195 | VK_Q(81), 196 | VK_QUOTE(222), 197 | VK_QUOTEDBL(152), 198 | VK_R(82), 199 | VK_RIGHT(39), 200 | VK_RIGHT_PARENTHESIS(522), 201 | VK_ROMAN_CHARACTERS(245), 202 | VK_S(83), 203 | VK_SCROLL_LOCK(145), 204 | VK_SEMICOLON(59), 205 | VK_SEPARATER(108), 206 | VK_SEPARATOR(108), 207 | VK_SHIFT(16), 208 | VK_SLASH(47), 209 | VK_SPACE(32), 210 | VK_STOP(65480), 211 | VK_SUBTRACT(109), 212 | VK_T(84), 213 | VK_TAB(9), 214 | VK_U(85), 215 | VK_UNDEFINED(0), 216 | VK_UNDERSCORE(523), 217 | VK_UNDO(65483), 218 | VK_UP(38), 219 | VK_V(86), 220 | VK_W(87), 221 | VK_WINDOWS(524), 222 | VK_X(88), 223 | VK_Y(89), 224 | VK_Z(90) 225 | ; 226 | 227 | private final int code; 228 | 229 | private eKeyEventCode(int code) { 230 | this.code = code; 231 | } 232 | 233 | public int getCode() { 234 | return this.code; 235 | } 236 | 237 | public static eKeyEventCode get(int code) { 238 | for (eKeyEventCode kec : eKeyEventCode.values()) { 239 | if (kec.code == code) { 240 | return kec; 241 | } 242 | } 243 | return null; 244 | } 245 | 246 | } 247 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/dwarf/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package {@code dev.hawala.dmachine.dwarf} contains the 3 | * technical components that make up the Dwarf application UI 4 | * for a single mesa engine. 5 | *6 | * These are classes necessary to give the mesa engine as visible interface 7 | * (black and white display pane for visualizing the mesa display memory, 8 | * callbacks implementation) as well as the main UI frame window for Dwarf 9 | * including classes for Java Swing event handling (listeners for keyboard, 10 | * mouse etc.) 11 | *
12 | */ 13 | package dev.hawala.dmachine.dwarf; -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine; 28 | 29 | /** 30 | * Configuration constants (with one exception) controlling the logging 31 | * and debugging behavior of the mesa engine, 32 | * 33 | * @author Dr. Hans-Walter Latz / Berlin (2017/2020) 34 | */ 35 | public class Config { 36 | 37 | /** 38 | * log recognized opcode implementations as they are scanned and added to dispatch tables? 39 | */ 40 | public static final boolean LOG_OPCODE_INSTALLATION = false; 41 | 42 | /** 43 | * log opcodes and their locations as they are executed? 44 | */ 45 | public static final boolean LOG_OPCODES = false; 46 | 47 | /** 48 | * log as flight recorder? 49 | * (i.e.: collect but do not write the data to stdout, speeding up 50 | * things, but having them at hand if needed, e.g. if a stack trap happens) 51 | * (slows down things, but not to the point as writing to stdout) 52 | */ 53 | public static final boolean LOG_OPCODES_AS_FLIGHTRECORDER = false; 54 | 55 | /** 56 | * prepend the stack data before the logged instruction in flight recorder mode? 57 | */ 58 | public static final boolean FLIGHTRECORDER_WITH_STACK = false; 59 | 60 | /** 61 | * log memory access locations and operations? 62 | */ 63 | public static final boolean LOG_MEM_ACCESS = false; 64 | 65 | /** 66 | * use interactive utility for debugging opcode execution? 67 | */ 68 | public static final boolean USE_DEBUG_INTERPRETER = false; 69 | 70 | /** 71 | * log BITBLT/BITBLTX/COLORBLT arguments and the like 72 | */ 73 | public static final boolean LOG_BITBLT_INSNS = false; 74 | 75 | /** 76 | * If LOG_BITBLT_INSNS is true, logging of BITBLT and friends will 77 | * only occur if they are executed while this flag is true. 78 | *36 | * A derived class usually defines a set of constants for the structure of the 37 | * FCB ({@code fcb_*}), commands ({@code Command_*}), status codes ({@code Status_*}) 38 | * etc., as necessary for communicating with Pilot. 39 | *
40 | *
41 | * Important fine point: When an agent asynchronously receives data from the device
42 | * it represents (e.g. from the UI or from the network), this data must be buffered
43 | * and may not be written directly to the mesa engines memory space, as the necessary
44 | * synchronizations would excessively slow down the mesa engine.
45 | *
46 | * An agent can freely access mesa memory when executing the {@code call()} method (thus
47 | * servicing a CALLAGENT instruction) and when executing the {@code refreshMesaMemory()} method,
48 | * which is called at more or less regular intervals by the mesa engine for exactly the purpose
49 | * of synchronizing the mesa memory with the external data changes accumulated so far.
50 | *
36 | * The purpose of this agent is to transfer the keyboard 37 | * events (already translated to {@code eLevelVKey}s) into 38 | * the bits in the FCB of this agent representing each key. 39 | *
40 | * 41 | * @author Dr. Hans-Walter Latz / Berlin (2017) 42 | */ 43 | public class KeyboardAgent extends Agent { 44 | 45 | /* 46 | * KeyboardFCBType (7 words for keystates) 47 | */ 48 | 49 | private static final int FCB_SIZE = 7; 50 | 51 | /* 52 | * key states 53 | */ 54 | private static final short ALL_KEYS_UP = (short)0xFFFF; 55 | 56 | private short[] uiKeys = new short[FCB_SIZE]; 57 | private boolean uiKeysChanged = false; 58 | 59 | public KeyboardAgent(int fcbAddress) { 60 | super(AgentDevice.keyboardAgent, fcbAddress, FCB_SIZE); 61 | 62 | this.enableLogging(Config.IO_LOG_KEYBOARD); 63 | 64 | for (int i = 0; i < FCB_SIZE; i++) { 65 | this.uiKeys[i] = ALL_KEYS_UP; 66 | } 67 | } 68 | 69 | @Override 70 | public void shutdown(StringBuilder errMsgTarget) { 71 | // nothing to shutdown for this agent 72 | } 73 | 74 | @Override 75 | public void call() { 76 | logf("call() - irrelevant, why is this called???\n"); 77 | } 78 | 79 | @Override 80 | protected void initializeFcb() { 81 | for (int i = 0; i < FCB_SIZE; i++) { 82 | this.setFcbWord(i, ALL_KEYS_UP); 83 | } 84 | } 85 | 86 | public synchronized void resetKeys() { 87 | for (int i = 0; i < FCB_SIZE; i++) { 88 | this.uiKeys[i] = ALL_KEYS_UP; 89 | } 90 | this.uiKeysChanged = true; 91 | this.logf("resetKeys()\n"); 92 | Processes.requestDataRefresh(); 93 | } 94 | 95 | public synchronized void handleKeyUsage(eLevelVKey key, boolean isPressed) { 96 | if (isPressed) { 97 | key.setPressed(this.uiKeys); 98 | } else { 99 | key.setReleased(this.uiKeys); 100 | } 101 | this.uiKeysChanged = true; 102 | this.logf("handleKeyUsage( key = %s, isPressed = %s )\n", key.toString(), (isPressed) ? "true" : "false"); 103 | Processes.requestDataRefresh(); 104 | } 105 | 106 | public synchronized void refreshMesaMemory() { 107 | if (this.uiKeysChanged) { 108 | this.logf("refreshMesaMemory() -> \n"); 109 | for (int i = 0; i < FCB_SIZE; i++) { 110 | short keySetting = this.uiKeys[i]; 111 | // logf(" | %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s |\n", 112 | // ((keySetting & 0x8000) != 0) ? "x" : " ", 113 | // ((keySetting & 0x4000) != 0) ? "x" : " ", 114 | // ((keySetting & 0x2000) != 0) ? "x" : " ", 115 | // ((keySetting & 0x1000) != 0) ? "x" : " ", 116 | // ((keySetting & 0x0800) != 0) ? "x" : " ", 117 | // ((keySetting & 0x0400) != 0) ? "x" : " ", 118 | // ((keySetting & 0x0200) != 0) ? "x" : " ", 119 | // ((keySetting & 0x0100) != 0) ? "x" : " ", 120 | // ((keySetting & 0x0080) != 0) ? "x" : " ", 121 | // ((keySetting & 0x0040) != 0) ? "x" : " ", 122 | // ((keySetting & 0x0020) != 0) ? "x" : " ", 123 | // ((keySetting & 0x0010) != 0) ? "x" : " ", 124 | // ((keySetting & 0x0008) != 0) ? "x" : " ", 125 | // ((keySetting & 0x0004) != 0) ? "x" : " ", 126 | // ((keySetting & 0x0002) != 0) ? "x" : " ", 127 | // ((keySetting & 0x0001) != 0) ? "x" : " " 128 | // ); 129 | this.setFcbWord(i, keySetting); 130 | } 131 | this.uiKeysChanged = false; 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/agents/NetworkInternalTimeService.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.agents; 28 | 29 | /** 30 | * Implementation of an intenal time service in case no network access is 31 | * configured. 32 | * 33 | * @author Dr. Hans-Walter Latz / Berlin (2018) 34 | */ 35 | public class NetworkInternalTimeService implements iNetDeviceInterface { 36 | 37 | private PacketActor notifier = null; 38 | private short[] timeResponse = null; 39 | 40 | private final short direction; // 0 = west, 1 = east 41 | private final short offsetHours; 42 | private final short offsetMinutes; 43 | 44 | private static long timeShiftMilliSeconds = 0; 45 | 46 | /** 47 | * Set the time adjustment ("days back in time") offset to be used 48 | * when the "current" time is retrieved by the mesa machine programs. 49 | * 50 | * @param seconds adjustment offset in seconds (negative values for shifting 51 | * the current time to the past. 52 | */ 53 | public static void setTimeShiftSeconds(long seconds) { 54 | timeShiftMilliSeconds = seconds * 1000; 55 | } 56 | 57 | /** 58 | * Initialize the internal time service with the time zone information 59 | * (without DST, meaning if DST is active, the {@code gmtOffsetMinutes} 60 | * value must be adjusted accordingly). 61 | * 62 | * @param gmtOffsetMinutes difference between local time and GMT in 63 | * minutes, with positive values being to the east and negative 64 | * to the west (e.g. Germany is +60 without DST and +120 with DST 65 | * whereas Alaska is -560 without DST resp -480 with DST). 66 | */ 67 | public NetworkInternalTimeService(int gmtOffsetMinutes) { 68 | if (gmtOffsetMinutes >= 0) { 69 | this.direction = 1; 70 | } else { 71 | this.direction = 0; 72 | gmtOffsetMinutes = -gmtOffsetMinutes; 73 | } 74 | gmtOffsetMinutes = gmtOffsetMinutes % 720; 75 | this.offsetHours = (short)(gmtOffsetMinutes / 60); 76 | this.offsetMinutes = (short)(gmtOffsetMinutes % 60); 77 | } 78 | 79 | @Override 80 | public void shutdown() { 81 | // nothing to shutdown... 82 | } 83 | 84 | @Override 85 | public synchronized void setNewPacketNotifier(PacketActor notifier) { 86 | this.notifier = notifier; 87 | } 88 | 89 | @Override 90 | public int enqueuePacket(byte[] srcBuffer, int byteCount, boolean feedback) { 91 | if ( this.readWord(srcBuffer, 0) != -1 92 | || this.readWord(srcBuffer, 1) != -1 93 | || this.readWord(srcBuffer, 2) != -1 94 | || this.readWord(srcBuffer, 6) != 0x0600) { // not broadcast or not xns 95 | return byteCount; 96 | } 97 | 98 | if (srcBuffer.length < 54 99 | || this.readWord(srcBuffer, 15) != 0x0008 100 | || this.readWord(srcBuffer, 9) != 0x0004) { // wrong length, target port not time or not PEX 101 | return byteCount; 102 | } 103 | 104 | if ( this.readWord(srcBuffer, 24) != 0x0001 105 | || this.readWord(srcBuffer, 25) != 0x0002 106 | || this.readWord(srcBuffer, 26) != 0x0001) { // not time packet type, wrong version, not request 107 | return byteCount; 108 | } 109 | 110 | // create time request response 111 | 112 | // the raw packet 113 | short[] b = new short[37]; 114 | 115 | // address components 116 | short myNet0 = 0x0004; 117 | short myNet1 = 0x0001; 118 | short myMac0 = 0x1000; 119 | short myMac1 = 0x1A33; 120 | short myMac2 = 0x3333; 121 | short mySocket = 8; 122 | short mac0 = this.readWord(srcBuffer, 3); 123 | short mac1 = this.readWord(srcBuffer, 4); 124 | short mac2 = this.readWord(srcBuffer, 5); 125 | 126 | // time data 127 | long unixTimeMillis = System.currentTimeMillis() + timeShiftMilliSeconds; 128 | int milliSecs = (int)(unixTimeMillis % 1000); 129 | long unixTimeSecs = unixTimeMillis / 1000; 130 | int mesaSecs = (int)((unixTimeSecs + (731 * 86400) + 2114294400) & 0x00000000FFFFFFFFL); 131 | short mesaSecs0 = (short)(mesaSecs >>> 16); 132 | short mesaSecs1 = (short)(mesaSecs & 0xFFFF); 133 | 134 | // build the packet component-wise 135 | 136 | // eth: dst 137 | b[0] = mac0; 138 | b[1] = mac1; 139 | b[2] = mac2; 140 | 141 | // eth: src 142 | b[3] = myMac0; 143 | b[4] = myMac1; 144 | b[5] = myMac2; 145 | 146 | // eth: type 147 | b[6] = 0x0600; 148 | 149 | // xns: ckSum 150 | b[7] = (short)0xFFFF; // no checksum 151 | 152 | // xns: length 153 | b[8] = 60; // payload length 154 | 155 | // xns: transport control & packet type 156 | b[9] = 4; // hop count = 0 & packet type = PEX 157 | 158 | // xns: destination endpoint: copy the source destination of the ingone packet 159 | b[10] = this.readWord(srcBuffer, 16); 160 | b[11] = this.readWord(srcBuffer, 17); 161 | b[12] = this.readWord(srcBuffer, 18); 162 | b[13] = this.readWord(srcBuffer, 19); 163 | b[14] = this.readWord(srcBuffer, 20); 164 | b[15] = this.readWord(srcBuffer, 21); 165 | 166 | // xns: source endpoint: put "our" address with the "local" net and "our" socket 167 | b[16] = myNet0; 168 | b[17] = myNet1; 169 | b[18] = myMac0; 170 | b[19] = myMac1; 171 | b[20] = myMac2; 172 | b[21] = mySocket; 173 | 174 | // pex: identification from request 175 | b[22] = this.readWord(srcBuffer, 22); 176 | b[23] = this.readWord(srcBuffer, 23); 177 | 178 | // pex: client type 179 | b[24] = 1; // clientType "time" 180 | 181 | // payload: time response 182 | b[25] = 2; // version(0): WORD -- TimeVersion = 2 183 | b[26] = 2; // tsBody(1): SELECT type(1): PacketType FROM -- timeResponse = 2 184 | b[27] = mesaSecs0; // time(2): WireLong -- computed time 185 | b[28] = mesaSecs1; 186 | b[29] = this.direction; // zoneS(4): System.WestEast -- east 187 | b[30] = this.offsetHours; // zoneH(5): [0..177B] -- +1 hour 188 | b[31] = this.offsetMinutes; // zoneM(6): [0..377B] -- +0 minutes 189 | b[32] = 0; // beginDST(7): WORD -- no dst (temp) 190 | b[33] = 0; // endDST(8): WORD -- no dst (temp) 191 | b[34] = 1; // errorAccurate(9): BOOLEAN -- true 192 | b[35] = 0; // absoluteError(10): WireLong] 193 | b[36] = (short)((milliSecs > 500) ? 1000 - milliSecs : milliSecs); // no direction ?? (plus or minus)? 194 | 195 | // enqueue for "receiving" the the service response 196 | this.setPacket(b); 197 | 198 | // done 199 | return byteCount; 200 | } 201 | 202 | @Override 203 | public int dequeuePacket(byte[] trgBuffer, int maxLength) { 204 | short[] packet = this.getPacket(); 205 | if (packet == null || trgBuffer == null || maxLength < 2) { 206 | return 0; 207 | } 208 | this.setPacket(null); // the only one was received... 209 | 210 | int trfWords = Math.min(maxLength / 2, packet.length); 211 | int bpos = 0; 212 | for (int i = 0; i < trfWords; i++) { 213 | trgBuffer[bpos++] = (byte)((packet[i] >> 8) & 0xFF); 214 | trgBuffer[bpos++] = (byte)(packet[i] & 0xFF); 215 | } 216 | 217 | return trfWords * 2; 218 | } 219 | 220 | /* 221 | * internals 222 | */ 223 | 224 | private short readWord(byte[] b, int wpos) { 225 | int bpos = wpos * 2; 226 | if (bpos < 0 || (bpos + 1) >= b.length) { 227 | return 0; 228 | } 229 | int hi = b[bpos++] & 0xFF; 230 | int lo = b[bpos] & 0xFF; 231 | short res = (short)(((hi << 8) | lo) & 0xFFFF); 232 | return res; 233 | } 234 | 235 | private synchronized short[] getPacket() { 236 | return this.timeResponse; 237 | } 238 | 239 | private synchronized void setPacket(short[] p) { 240 | this.timeResponse = p; 241 | 242 | if (this.notifier != null) { 243 | try { 244 | this.notifier.handleSinglePacket(); 245 | } catch (InterruptedException e) { 246 | // ignored 247 | } 248 | } 249 | } 250 | 251 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/agents/NullAgent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.agents; 28 | 29 | import dev.hawala.dmachine.engine.Cpu; 30 | 31 | /** 32 | * Agent for the null device, doing effectively nothing. 33 | * 34 | * @author Dr. Hans-Walter Latz / Berlin (2017) 35 | */ 36 | public class NullAgent extends Agent { 37 | 38 | private static final int FCB_SIZE = 0; 39 | 40 | public NullAgent(int fcbAddress) { 41 | super(AgentDevice.nullAgent, fcbAddress, FCB_SIZE); 42 | } 43 | 44 | @Override 45 | public void shutdown(StringBuilder errMsgTarget) { 46 | // nothing to shutdown for this agent 47 | } 48 | 49 | @Override 50 | public void refreshMesaMemory() { 51 | // nothing to transfer to mesa memory for this agent 52 | } 53 | 54 | @Override 55 | public void call() { 56 | Cpu.ERROR("NullAgent.call :: invalid invocation of nullAgent"); 57 | } 58 | 59 | @Override 60 | protected void initializeFcb() { 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/agents/ParallelAgent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.agents; 28 | 29 | import dev.hawala.dmachine.engine.Cpu; 30 | 31 | /** 32 | * Agent for the parallel interface of a Dwarf engine (unsupported). 33 | * 34 | * @author Dr. Hans-Walter Latz / Berlin (2017) 35 | */ 36 | public class ParallelAgent extends Agent { 37 | 38 | /* 39 | * unsupported so far 40 | */ 41 | private static final int FCB_SIZE = 0; 42 | 43 | public ParallelAgent(int fcbAddress) { 44 | super(AgentDevice.parallelAgent, fcbAddress, FCB_SIZE); 45 | } 46 | 47 | @Override 48 | public void shutdown(StringBuilder errMsgTarget) { 49 | // nothing to shutdown for this agent 50 | } 51 | 52 | @Override 53 | public void refreshMesaMemory() { 54 | // nothing to transfer to mesa memory for this agent 55 | } 56 | 57 | @Override 58 | public void call() { 59 | Cpu.ERROR("ParallelAgent.call :: invalid invocation of parallelAgent"); 60 | } 61 | 62 | @Override 63 | protected void initializeFcb() { 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/agents/ProcessorAgent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.agents; 28 | 29 | import java.time.LocalDate; 30 | import java.util.Date; 31 | 32 | import dev.hawala.dmachine.engine.Cpu; 33 | import dev.hawala.dmachine.engine.Mem; 34 | 35 | /** 36 | * Agent providing access to machine characteristics and the clock 37 | * of a Dwarf machine, 38 | * 39 | * @author Dr. Hans-Walter Latz / Berlin (2017) 40 | */ 41 | public class ProcessorAgent extends Agent { 42 | 43 | /* 44 | * ProcessorFCBType 45 | */ 46 | private static final int fcb_w_processorID0 = 0; 47 | private static final int fcb_w_processorID1 = 1; 48 | private static final int fcb_w_processorID2 = 2; 49 | private static final int fcb_w_microsecondsPerHundredPulses = 3; 50 | private static final int fcb_w_millisecondsPerTick = 4; 51 | private static final int fcb_w_alignmentFiller = 5; 52 | private static final int fcb_dbl_realMemoryPageCount = 6; 53 | private static final int fcb_dbl_virtualMemoryPageCount = 8; 54 | private static final int fcb_dbl_gmt = 10; 55 | private static final int fcb_w_command = 12; 56 | private static final int fcb_w_status = 13; // ProcessorStatus 57 | private static final int FCB_SIZE = 14; 58 | 59 | // ProcessorCommand: TYPE = MACHINE DEPENDENT {noop(0), readGMT(1), writeGMT(2)}; 60 | private static final short Command_noop = 0; 61 | private static final short Command_readGMT = 1; 62 | private static final short Command_writeGMT = 2; 63 | 64 | // ProcessorStatus: TYPE = MACHINE DEPENDENT { 65 | // inProgress(0), success(1), failure(2)}; 66 | private static final short Status_inProgress = 0; 67 | private static final short Status_success = 1; 68 | private static final short Status_failure = 2; 69 | 70 | // difference between (our) simulated GMT and (Pilots) expected GMT 71 | private int gmtCorrection = 0; 72 | 73 | // work-around for XDE HeraldWindow having a blinking warning instead of the date 74 | // if the "current" time is not in the expected time frame (somewhere between the bootfile 75 | // build date and some (4 or 5) years later) 76 | // so the system date can be faked (at a 2nd level :-)) to a given date for the first n-thousand 77 | // instructions, so the HeraldWindow sees a specific date when it checks for a plausible boot time 78 | // and the "correct" date is returned after that number of instructions when "the rest of XDE" asks 79 | // for the time 80 | private static long xdeNoBlinkInsnLimit = 0; 81 | private static long xdeNoBlinkBaseMSecs = 0; 82 | private static long xdeNoBlinkDateMSecs = 0; 83 | 84 | public static void installXdeNoBlinkWorkAround(LocalDate noBlinkTargetDate, long insnsLimit) { 85 | xdeNoBlinkInsnLimit = insnsLimit; 86 | xdeNoBlinkBaseMSecs = (System.currentTimeMillis() / 86_400_000L) * 86_400_000L; // midnight of today 87 | xdeNoBlinkDateMSecs = noBlinkTargetDate.toEpochDay() * 86_400_000L; // date to be returned until insnsLimit instructions are reached 88 | } 89 | 90 | public ProcessorAgent(int fcbAddress) { 91 | super(AgentDevice.processorAgent, fcbAddress, FCB_SIZE); 92 | } 93 | 94 | @Override 95 | public void shutdown(StringBuilder errMsgTarget) { 96 | // nothing to shutdown for this agent 97 | } 98 | 99 | @Override 100 | public void refreshMesaMemory() { 101 | // nothing to transfer to mesa memory for this agent 102 | } 103 | 104 | @Override 105 | public void call() { 106 | short cmd = this.getFcbWord(fcb_w_command); 107 | switch(cmd) { 108 | case Command_noop: 109 | this.setFcbWord(fcb_w_status, Status_success); 110 | break; 111 | 112 | case Command_readGMT: 113 | if (Cpu.insns > xdeNoBlinkInsnLimit) { 114 | this.setFcbDblWord(fcb_dbl_gmt, getRawPilotTime() + gmtCorrection); 115 | } else { 116 | this.setFcbDblWord(fcb_dbl_gmt, getRawPilotTime(xdeNoBlinkDateMSecs + (System.currentTimeMillis() - xdeNoBlinkBaseMSecs))); 117 | } 118 | this.setFcbWord(fcb_w_status, Status_success); 119 | break; 120 | 121 | case Command_writeGMT: 122 | gmtCorrection = this.getFcbDblWord(fcb_dbl_gmt) - getRawPilotTime(); 123 | this.setFcbWord(fcb_w_status, Status_success); 124 | break; 125 | 126 | default: 127 | this.setFcbWord(fcb_w_status, Status_failure); 128 | break; 129 | } 130 | } 131 | 132 | @Override 133 | protected void initializeFcb() { 134 | this.setFcbWord(fcb_w_processorID0, Cpu.getPIDword(1)); 135 | this.setFcbWord(fcb_w_processorID1, Cpu.getPIDword(2)); 136 | this.setFcbWord(fcb_w_processorID2, Cpu.getPIDword(3)); 137 | this.setFcbWord(fcb_w_microsecondsPerHundredPulses, Cpu.MicrosecondsPerPulse * 100); 138 | this.setFcbWord(fcb_w_millisecondsPerTick, (Cpu.MicrosecondsPerPulse * Cpu.TimeOutInterval) / 1000); 139 | this.setFcbWord(fcb_w_alignmentFiller, 0); 140 | this.setFcbDblWord(fcb_dbl_realMemoryPageCount, Mem.getRealPagesSize()); 141 | this.setFcbDblWord(fcb_dbl_virtualMemoryPageCount, Mem.getVirtualPagesSize()); 142 | this.setFcbDblWord(fcb_dbl_gmt, getRawPilotTime() + gmtCorrection); 143 | this.setFcbWord(fcb_w_command, Command_noop); 144 | this.setFcbWord(fcb_w_status, Status_success); 145 | } 146 | 147 | 148 | // Java Time base :: 1970-01-01 00:00:00 149 | // Pilot Time base :: 1968-01-01 00:00:00 150 | // => difference is 1 year + 1 leap-year => 731 days. 151 | private static final int UnixToPilotSecondsDiff = 731 * 86400; // seconds 152 | 153 | // this is some unexplainable Xerox constant whatever for, but we have to use it... 154 | private static final int MesaGmtEpoch = 2114294400; 155 | 156 | // get seconds since 1968-01-01 00:00:00 for a given Jaja milliseconds timestamp 157 | private static int getRawPilotTime(long msecs) { 158 | long currJavaTimeInSeconds = msecs / 1000; 159 | return (int)((currJavaTimeInSeconds + UnixToPilotSecondsDiff + MesaGmtEpoch) & 0x00000000FFFFFFFFL); 160 | } 161 | 162 | // get seconds since 1968-01-01 00:00:00 for "now" 163 | private static int getRawPilotTime() { 164 | return getRawPilotTime(System.currentTimeMillis()); 165 | } 166 | 167 | /** 168 | * Get the corresponding Java-{@code Date} for a given mesa-time. 169 | * 170 | * @param mesaTime the mesa time value to translate. 171 | * @return the Java-{@code Date} corrsponding to {@code mesaQTime}. 172 | */ 173 | public static Date getJavaTime(int mesaTime) { 174 | long javaMillis = (mesaTime - UnixToPilotSecondsDiff - MesaGmtEpoch) * 1000L; 175 | return new Date(javaMillis); 176 | } 177 | 178 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/agents/ReservedAgent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.agents; 28 | 29 | import dev.hawala.dmachine.engine.Cpu; 30 | 31 | /** 32 | * Implementation for one of the "reserved" agents. 33 | * 34 | * @author Dr. Hans-Walter Latz / Berlin (2017) 35 | */ 36 | public class ReservedAgent extends Agent { 37 | 38 | private static final int FCB_SIZE = 0; 39 | 40 | public ReservedAgent(AgentDevice device, int fcbAddress) { 41 | super(device, fcbAddress, FCB_SIZE); 42 | } 43 | 44 | @Override 45 | public void shutdown(StringBuilder errMsgTarget) { 46 | // nothing to shutdown for this agent 47 | } 48 | 49 | @Override 50 | public void refreshMesaMemory() { 51 | // nothing to transfer to mesa memory for this agent 52 | } 53 | 54 | @Override 55 | public void call() { 56 | Cpu.ERROR("ReservedAgent.call :: invalid invocation of " + this.agentType.name()); 57 | } 58 | 59 | @Override 60 | protected void initializeFcb() { 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/agents/SerialAgent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.agents; 28 | 29 | import dev.hawala.dmachine.engine.Cpu; 30 | 31 | /** 32 | * Agent for the RS-232 serial interface of a Dwarf machine 33 | * (unsupported). 34 | * 35 | * @author Dr. Hans-Walter Latz / Berlin (2017) 36 | */ 37 | public class SerialAgent extends Agent { 38 | 39 | private static final int FCB_SIZE = 0; 40 | 41 | public SerialAgent(int fcbAddress) { 42 | super(AgentDevice.serialAgent, fcbAddress, FCB_SIZE); 43 | } 44 | 45 | @Override 46 | public void shutdown(StringBuilder errMsgTarget) { 47 | // currently nothing to shutdown for this agent 48 | } 49 | 50 | @Override 51 | public void refreshMesaMemory() { 52 | // nothing to transfer to mesa memory for this agent 53 | } 54 | 55 | @Override 56 | public void call() { 57 | Cpu.ERROR("SerialAgent.call :: invalid invocation of serialAgent"); 58 | } 59 | 60 | @Override 61 | protected void initializeFcb() { 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/agents/StreamAgent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.agents; 28 | 29 | import dev.hawala.dmachine.engine.PrincOpsDefs; 30 | 31 | /** 32 | * Agent for stream-attached "devices" or "coprocessors", i.e. external 33 | * programs and libraries on the "outside" of the mesa engine (i.e. the 34 | * OS where the mesa emulator runs), providing various services like local 35 | * printing, access to the file system, document conversion, copy&paste, 36 | * drag&drop or the like. 37 | *106 | * When a NotifyIOP instruction is executed, this method will be called for all device 107 | * handlers up to the first handler returning {@code true}. 108 | *
109 | * 110 | * @return {@code true} if this device handler was identified by the {@code notifyMask} 111 | * (independently of the outcome (successful or not) if processing happened). 112 | */ 113 | public abstract boolean processNotify(short notifyMask); 114 | 115 | /** 116 | * Operation codes for LOCKMEM instruction 117 | */ 118 | public enum MemOperation { add(0), and(1), or(2), xchg(3), overwriteIfNil(4); 119 | public final int code; 120 | private MemOperation(int code) { this.code = code; } 121 | } 122 | 123 | /** 124 | * Handle synchronized access to memory among the mesa machine and the IOP. 125 | * 126 | * @param lockMask 127 | * @param realAddress 128 | * @param memOp 129 | * @param oldValue 130 | * @param newValue 131 | */ 132 | public abstract void handleLockmem(short lockMask, int realAddress, MemOperation memOp, short oldValue, short newValue); 133 | 134 | /** 135 | * Optionally cleanup at the end of the LOCKMEM processing. 136 | * 137 | * @param lockMask 138 | * @param realAddress 139 | */ 140 | public void cleanupAfterLockmem(short lockMask, int realAddress) { 141 | // default: do nothing 142 | } 143 | 144 | public abstract void handleLockqueue(int vAddr, int rAddr); 145 | 146 | /** 147 | * Copy all buffered new external data into mesa memory space. 148 | */ 149 | public abstract void refreshMesaMemory(); 150 | 151 | /** 152 | * Stop usage of the device and save buffers or the devices state if necessary. 153 | * 154 | * @param errMsgTarget target for messages during shutdown, indicating that there were errors 155 | */ 156 | public abstract void shutdown(StringBuilder errMsgTarget); 157 | 158 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/iop6085/HBeep.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2019, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.iop6085; 28 | 29 | import static dev.hawala.dmachine.engine.iop6085.IORegion.*; 30 | 31 | import dev.hawala.dmachine.engine.Config; 32 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.IOPCondition; 33 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.NotifyMask; 34 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.TaskContextBlock; 35 | import dev.hawala.dmachine.engine.iop6085.IORegion.IORAddress; 36 | 37 | /** 38 | * IOP device handler for the beeper (dummy, no sounds provided for now). 39 | * 40 | * @author Dr. Hans-Walter Latz / Berlin (2019,2020) 41 | */ 42 | public class HBeep extends DeviceHandler { 43 | 44 | private static final String BeepFCB = "BeepFCB"; 45 | 46 | private static class FCB implements IORAddress { 47 | private final int startAddress; 48 | 49 | public final TaskContextBlock beepTask; 50 | public final IOPCondition beepCndt; 51 | public final NotifyMask beepMask; 52 | public final Word frequency; 53 | 54 | private FCB() { 55 | this.startAddress = IORegion.syncToSegment() + IORegion.IOR_BASE; 56 | 57 | this.beepTask = new TaskContextBlock(BeepFCB, "beepTask"); 58 | this.beepCndt = new IOPCondition(BeepFCB, "beepCndt"); 59 | this.beepMask = new NotifyMask(BeepFCB, "beepMask"); 60 | this.frequency = mkByteSwappedWord(BeepFCB, "frequency"); 61 | 62 | this.beepMask.byteMaskAndOffset.set(mkMask()); 63 | } 64 | 65 | 66 | @Override 67 | public String getName() { 68 | return BeepFCB; 69 | } 70 | 71 | 72 | @Override 73 | public int getRealAddress() { 74 | return this.startAddress; 75 | } 76 | } 77 | 78 | /* 79 | * implementation of the iop6085 beep device handler 80 | */ 81 | 82 | private final FCB fcb; 83 | 84 | public HBeep() { 85 | super(BeepFCB, Config.IO_LOG_DISPLAY); 86 | this.fcb = new FCB(); 87 | } 88 | 89 | @Override 90 | public int getFcbRealAddress() { 91 | return this.fcb.getRealAddress(); 92 | } 93 | 94 | @Override 95 | public short getFcbSegment() { 96 | return this.fcb.getIOPSegment(); 97 | } 98 | 99 | @Override 100 | public boolean processNotify(short notifyMask) { 101 | // check if it's for us 102 | if (notifyMask != this.fcb.beepMask.byteMaskAndOffset.get()) { 103 | return false; 104 | } 105 | 106 | // simulate beeping on / off 107 | this.logf("processNotify -> frequency = %d (units??)\n", this.fcb.frequency.get() & 0xFFFF); 108 | // megaHertz: LONG CARDINAL <- 2764800; 109 | // fcb.frequency <- ByteSwap[Inline.LowHalf[Inline.LongDiv[megaHertz, MAX[frequency, 43]]]] 110 | 111 | // done 112 | return true; 113 | } 114 | 115 | @Override 116 | public void handleLockmem(short lockMask, int realAddress, MemOperation memOp, short oldValue, short newValue) { 117 | // not relevant 118 | } 119 | 120 | @Override 121 | public void handleLockqueue(int vAddr, int rAddr) { 122 | // not relevant for beep handler 123 | } 124 | 125 | @Override 126 | public synchronized void refreshMesaMemory() { 127 | // not relevant 128 | } 129 | 130 | @Override 131 | public void shutdown(StringBuilder errMsgTarget) { 132 | // nothing to save or shutdown 133 | } 134 | 135 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/iop6085/HKeyboardMouse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2019, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.iop6085; 28 | 29 | import static dev.hawala.dmachine.engine.iop6085.IORegion.*; 30 | 31 | import dev.hawala.dmachine.engine.Config; 32 | import dev.hawala.dmachine.engine.Processes; 33 | import dev.hawala.dmachine.engine.eLevelVKey; 34 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.TaskContextBlock; 35 | import dev.hawala.dmachine.engine.iop6085.IORegion.IORAddress; 36 | 37 | /** 38 | * IOP device handler for the keyboard and mouse of a Daybreak/6085 machine. 39 | * 40 | * @author Dr. Hans-Walter Latz / Berlin (2019,2020) 41 | */ 42 | public class HKeyboardMouse extends DeviceHandler { 43 | 44 | /* 45 | * key states 46 | */ 47 | private static final int KEYBITS_WORDS = 9; 48 | 49 | private static final short ALL_KEYS_UP = (short)0xFFFF; 50 | 51 | private short[] uiKeys = new short[KEYBITS_WORDS]; 52 | private boolean uiKeysChanged = false; 53 | 54 | /* 55 | * Function Control Block 56 | */ 57 | 58 | private static final String KeyMoFCB = "KeyboardMouseFCB"; 59 | 60 | private static class FCB implements IORAddress { 61 | private final int startAddress; 62 | 63 | public final TaskContextBlock keyBoardAndMouseTask; 64 | public final Word hexValue_convertKeyCodeToBit; 65 | public final Word frameErrorCnt; 66 | public final Word overRunErrorCnt; 67 | public final Word parityErrorCnt; 68 | public final Word spuriousIntCnt; 69 | public final Word watchDogCnt; 70 | public final Word badInterruptCnt; 71 | public final Word mouseX; 72 | public final Word mouseY; 73 | public final Word[] kBbase = new Word[KEYBITS_WORDS]; 74 | public final Word[] kBindex = new Word[128]; 75 | 76 | private FCB() { 77 | this.startAddress = IORegion.syncToSegment() + IORegion.IOR_BASE; 78 | 79 | this.keyBoardAndMouseTask = new TaskContextBlock(KeyMoFCB, "displayTCB"); 80 | this.hexValue_convertKeyCodeToBit = mkWord(KeyMoFCB, "hexValue+convertKeyCodeToBit"); 81 | this.frameErrorCnt = mkByteSwappedWord(KeyMoFCB, "frameErrorCnt"); 82 | this.overRunErrorCnt = mkByteSwappedWord(KeyMoFCB, "overRunErrorCnt"); 83 | this.parityErrorCnt = mkByteSwappedWord(KeyMoFCB, "parityErrorCnt"); 84 | this.spuriousIntCnt = mkByteSwappedWord(KeyMoFCB, "spuriousIntCnt"); 85 | this.watchDogCnt = mkByteSwappedWord(KeyMoFCB, "watchDogCnt"); 86 | this.badInterruptCnt = mkByteSwappedWord(KeyMoFCB, "badInterruptCnt"); 87 | this.mouseX = mkWord(KeyMoFCB, "mouseX"); 88 | this.mouseY = mkWord(KeyMoFCB, "mouseY"); 89 | for (int i = 0; i < this.kBbase.length; i++) { 90 | this.kBbase[i] = mkWord(KeyMoFCB, "kBbase[" + i +"]"); 91 | } 92 | for (int i = 0; i < this.kBindex.length; i++) { 93 | this.kBindex[i] = mkWord(KeyMoFCB, "kBindex[" + i +"]"); 94 | } 95 | 96 | } 97 | 98 | @Override 99 | public String getName() { 100 | return KeyMoFCB; 101 | } 102 | 103 | @Override 104 | public int getRealAddress() { 105 | return this.startAddress; 106 | } 107 | 108 | } 109 | 110 | /* 111 | * implementation of the iop6085 keyboard and mouse interface 112 | */ 113 | 114 | private final FCB fcb; 115 | 116 | public HKeyboardMouse() { 117 | super(KeyMoFCB, Config.IO_LOG_KEYBOARD | Config.IO_LOG_MOUSE); 118 | 119 | this.fcb = new FCB(); 120 | 121 | for (int i = 0; i < KEYBITS_WORDS; i++) { 122 | this.fcb.kBbase[i].set(ALL_KEYS_UP); 123 | this.uiKeys[i] = ALL_KEYS_UP; 124 | } 125 | this.uiKeysChanged = false; 126 | } 127 | 128 | @Override 129 | public int getFcbRealAddress() { 130 | return this.fcb.getRealAddress(); 131 | } 132 | 133 | @Override 134 | public short getFcbSegment() { 135 | return this.fcb.getIOPSegment(); 136 | } 137 | 138 | @Override 139 | public boolean processNotify(short notifyMask) { 140 | // no active notifications by client 141 | return false; 142 | } 143 | 144 | @Override 145 | public void handleLockmem(short lockMask, int realAddress, MemOperation memOp, short oldValue, short newValue) { 146 | // no synchronization necessary with client (access to fcb fields serialized through refreshMesaMemory(), see below) 147 | } 148 | 149 | @Override 150 | public void handleLockqueue(int vAddr, int rAddr) { 151 | // not relevant for keyboard/mouse handler 152 | } 153 | 154 | @Override 155 | public void shutdown(StringBuilder errMsgTarget) { 156 | // nothing to save or shutdown 157 | } 158 | 159 | @Override 160 | public synchronized void refreshMesaMemory() { 161 | // transfer keyboard states from UI area to mesa memory 162 | if (this.uiKeysChanged) { 163 | for (int i = 0; i < KEYBITS_WORDS; i++) { 164 | this.fcb.kBbase[i].set(this.uiKeys[i]); 165 | } 166 | this.uiKeysChanged = false; 167 | } 168 | } 169 | 170 | public synchronized void handleKeyUsage(eLevelVKey key, boolean isPressed) { 171 | if (isPressed) { 172 | key.setPressed(this.uiKeys); 173 | } else { 174 | key.setReleased(this.uiKeys); 175 | } 176 | this.uiKeysChanged = true; 177 | this.logf("handleKeyUsage( key = %s, isPressed = %s )\n", key.toString(), (isPressed) ? "true" : "false"); 178 | Processes.requestDataRefresh(); 179 | } 180 | 181 | public synchronized void resetKeys() { 182 | for (int i = 0; i < KEYBITS_WORDS; i++) { 183 | this.uiKeys[i] = ALL_KEYS_UP; 184 | } 185 | this.uiKeysChanged = true; 186 | Processes.requestDataRefresh(); 187 | } 188 | 189 | // must be called by the display device during a refreshMesaMemory() method, i.e. from the mesa processor thread! 190 | public void setNewCursorPosition(short x, short y) { 191 | this.fcb.mouseX.set(x); 192 | this.fcb.mouseY.set(y); 193 | } 194 | 195 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/iop6085/HTTY.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2019, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.iop6085; 28 | 29 | import static dev.hawala.dmachine.engine.iop6085.IORegion.mkByteSwappedWord; 30 | import static dev.hawala.dmachine.engine.iop6085.IORegion.mkIOPBoolean; 31 | import static dev.hawala.dmachine.engine.iop6085.IORegion.mkWord; 32 | 33 | import dev.hawala.dmachine.engine.Config; 34 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.ClientCondition; 35 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.IOPCondition; 36 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.NotifyMask; 37 | import dev.hawala.dmachine.engine.iop6085.IOPTypes.TaskContextBlock; 38 | import dev.hawala.dmachine.engine.iop6085.IORegion.IOPBoolean; 39 | import dev.hawala.dmachine.engine.iop6085.IORegion.IORAddress; 40 | import dev.hawala.dmachine.engine.iop6085.IORegion.Word; 41 | 42 | /** 43 | * IOP device handler for the unsupported TTY device of a Daybreak/6085 machine. 44 | * 45 | * @author Dr. Hans-Walter Latz / Berlin (2019,2020) 46 | */ 47 | public class HTTY extends DeviceHandler { 48 | 49 | /* 50 | * Function Control Block 51 | */ 52 | 53 | private static final String TTYFCB = "TTYFCB"; 54 | 55 | private static class WorkListType { 56 | private final IOPBoolean writeBaudRate; 57 | 58 | private WorkListType(String name) { 59 | this.writeBaudRate = mkIOPBoolean(name, "writeBaudRate"); 60 | } 61 | } 62 | 63 | private static class FCB implements IORAddress { 64 | private final int startAddress; 65 | 66 | public final TaskContextBlock txTcb; 67 | public final TaskContextBlock specRxTcb; 68 | public final TaskContextBlock rxTaskChBTcb; 69 | 70 | public final Word ttyLockMask; 71 | public final NotifyMask ttyWorkMask; 72 | public final ClientCondition ttyClientCondition; 73 | public final IOPCondition ttyWorkCondition; 74 | 75 | public final Word txBuffer; // CHARACTER 76 | public final Word rxBuffer; // CHARACTER 77 | 78 | public final Word ttyWorkList; // MACHINE DEPENDENT with 16 BOOLEANs 79 | 80 | public final Word ttyBaudRate; 81 | public final Word wr1_wr3; 82 | public final Word wr4_wr5; 83 | 84 | public final Word iopSystemInputPort_rr0; 85 | public final Word rr1_rr2; 86 | 87 | public final Word ttyStatusWord; 88 | 89 | public final Word eepromImage_type; // MACHINE DEPENDENT {none(0), DCE(2), (LAST [CARDINAL])} 90 | public final Word eepromImage_attributes1; 91 | public final Word eepromImage_attributes2; 92 | public final Word eepromImage_attributes3; 93 | public final Word eepromImage_attributes4; 94 | 95 | private FCB() { 96 | this.startAddress = IORegion.syncToSegment() + IORegion.IOR_BASE; 97 | 98 | this.txTcb = new TaskContextBlock(TTYFCB, "txTcb"); 99 | this.specRxTcb = new TaskContextBlock(TTYFCB, "specRxTcb"); 100 | this.rxTaskChBTcb = new TaskContextBlock(TTYFCB, "rxTaskChBTcb"); 101 | 102 | this.ttyLockMask = mkWord(TTYFCB, "ttyLockMask"); 103 | this.ttyWorkMask = new NotifyMask(TTYFCB, "ttyWorkMask"); 104 | this.ttyClientCondition = new ClientCondition(TTYFCB, "ttyClientCondition"); 105 | this.ttyWorkCondition = new IOPCondition(TTYFCB, "ttyWorkCondition"); 106 | 107 | this.txBuffer = mkWord(TTYFCB, "txBuffer"); 108 | this.rxBuffer = mkWord(TTYFCB, "rxBuffer"); 109 | 110 | this.ttyWorkList = mkWord(TTYFCB, "ttyWorkList"); 111 | 112 | this.ttyBaudRate = mkByteSwappedWord(TTYFCB, "ttyBaudRate"); 113 | this.wr1_wr3 = mkWord(TTYFCB, "wr1+wr3"); 114 | this.wr4_wr5 = mkWord(TTYFCB, "wr4+wr5"); 115 | 116 | this.iopSystemInputPort_rr0 = mkWord(TTYFCB, "iopSystemInputPort+rr0"); 117 | this.rr1_rr2 = mkWord(TTYFCB, "rr1+rr2"); 118 | 119 | this.ttyStatusWord = mkWord(TTYFCB, "ttyStatusWord"); 120 | 121 | this.eepromImage_type = mkWord(TTYFCB, "eepromImage.type"); 122 | this.eepromImage_attributes1 = mkWord(TTYFCB, "eepromImage_attributes[1]"); 123 | this.eepromImage_attributes2 = mkWord(TTYFCB, "eepromImage_attributes[2]"); 124 | this.eepromImage_attributes3 = mkWord(TTYFCB, "eepromImage_attributes[3]"); 125 | this.eepromImage_attributes4 = mkWord(TTYFCB, "eepromImage_attributes[4]"); 126 | 127 | // initialize notification mask 128 | this.ttyWorkMask.byteMaskAndOffset.set(mkMask()); 129 | } 130 | 131 | @Override 132 | public String getName() { 133 | return TTYFCB; 134 | } 135 | 136 | @Override 137 | public int getRealAddress() { 138 | return this.startAddress; 139 | } 140 | 141 | } 142 | 143 | /* 144 | * implementation of the iop6085 tty interface 145 | */ 146 | 147 | private final FCB fcb; 148 | 149 | public HTTY() { 150 | super(TTYFCB, Config.IO_LOG_TTY); 151 | 152 | this.fcb = new FCB(); 153 | } 154 | 155 | @Override 156 | public int getFcbRealAddress() { 157 | return this.fcb.getRealAddress(); 158 | } 159 | 160 | @Override 161 | public short getFcbSegment() { 162 | return this.fcb.getIOPSegment(); 163 | } 164 | 165 | @Override 166 | public boolean processNotify(short notifyMask) { 167 | // check if it's for us 168 | if (notifyMask != this.fcb.ttyWorkMask.byteMaskAndOffset.get()) { 169 | return false; 170 | } 171 | 172 | this.logf("IOP::HTTY.processNotify() - unimplemented yet ...\n"); 173 | 174 | return true; 175 | } 176 | 177 | @Override 178 | public void handleLockmem(short lockMask, int realAddress, MemOperation memOp, short oldValue, short newValue) { 179 | // TTY device currently unsupported/unused 180 | } 181 | 182 | @Override 183 | public void handleLockqueue(int vAddr, int rAddr) { 184 | // TTY device currently unsupported/unused 185 | } 186 | 187 | @Override 188 | public void refreshMesaMemory() { 189 | // TTY device currently unsupported/unused 190 | } 191 | 192 | @Override 193 | public void shutdown(StringBuilder errMsgTarget) { 194 | // TTY device currently unsupported/unused 195 | } 196 | 197 | } -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/iop6085/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package {@code dev.hawala.dmachine.engine.iop6085} has the 3 | * implementations for the device handlers which provide the emulated 4 | * devices of a 6085/daybreak machine attached to the mesa engine. 5 | *6 | * For the network device, the network classes implementing the interface to 7 | * Dodos nethub resp. the internal time service are re-used from the sibling 8 | * Agents package. 9 | *
10 | */ 11 | package dev.hawala.dmachine.engine.iop6085; -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/opcodes/Ch03_Memory_Organization.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.opcodes; 28 | 29 | import dev.hawala.dmachine.engine.Cpu; 30 | import dev.hawala.dmachine.engine.Mem; 31 | import dev.hawala.dmachine.engine.Opcodes.OpImpl; 32 | import dev.hawala.dmachine.engine.PrincOpsDefs; 33 | import dev.hawala.dmachine.engine.Processes; 34 | 35 | /** 36 | * Implementation of instructions defined in PrincOps 4.0 37 | * in chapter: 3 Memory Organization. 38 | * 39 | * @author Dr. Hans-Walter Latz / Berlin (2017) 40 | */ 41 | public class Ch03_Memory_Organization { 42 | 43 | /* 44 | * 3.1.2 Memory Map Instructions 45 | */ 46 | 47 | // SM - Set Map 48 | public static final OpImpl ESC_x07_SM = () -> { 49 | short mf = Cpu.pop(); 50 | int rp = Cpu.popLong(); 51 | int vp = Cpu.popLong(); 52 | 53 | Mem.setMap("SM", vp, rp, mf); 54 | }; 55 | 56 | // GMF - Get Map Flags 57 | public static final OpImpl ESC_x09_GMF = () -> { 58 | int vp = Cpu.popLong(); 59 | short mf = Mem.getVPageFlags(vp); 60 | int rp = Mem.getVPageRealPage(vp); 61 | 62 | Cpu.push(mf); 63 | Cpu.pushLong(rp); 64 | }; 65 | 66 | // SMF - Set Map Flags 67 | public static final OpImpl ESC_x08_SMF = () -> { 68 | short newMf = Cpu.pop(); 69 | int vp = Cpu.popLong(); 70 | short mf = Mem.getVPageFlags(vp); 71 | int rp = Mem.getVPageRealPage(vp); 72 | 73 | Cpu.push(mf); 74 | Cpu.pushLong(rp); 75 | if (!Mem.isVacant(mf)) { 76 | Cpu.logf(" SMF -> setMap(vp, rp, newMf)\n"); 77 | Mem.setMap("SMF", vp, rp, newMf); 78 | } 79 | }; 80 | 81 | /* 82 | * 3.2.1 Main Data Space Access 83 | */ 84 | 85 | // LP - Lengthen Pointer 86 | public static final OpImpl OPC_xF7_LP = () -> { 87 | short ptr = Cpu.pop(); 88 | Cpu.pushLong((ptr == 0) ? 0 : Cpu.lengthenPointer(ptr)); 89 | }; 90 | 91 | /* 92 | * 3.2.3 Frame Overhead Access 93 | */ 94 | 95 | // ROB - Read Overhead Byte 96 | public static final OpImpl ESC_x1E_ROB_alpha = () -> { 97 | int alpha = Mem.getNextCodeByte(); 98 | int ptr = Cpu.pop() & 0xFFFF; 99 | if (alpha < 1 || alpha > 4) { Cpu.ERROR("ROB :: invalid alpha = " + alpha); } 100 | Cpu.push(Mem.readMDSWord(ptr - alpha)); 101 | }; 102 | 103 | // WOB - Write Overhead Byte 104 | public static final OpImpl ESC_x1F_WOB_alpha = () -> { 105 | int alpha = Mem.getNextCodeByte(); 106 | int ptr = Cpu.pop() & 0xFFFF; 107 | if (alpha < 1 || alpha > 4) { Cpu.ERROR("WOB :: invalid alpha = " + alpha); } 108 | Mem.writeMDSWord(ptr - alpha, Cpu.pop()); 109 | }; 110 | 111 | /* 112 | * 3.3.4 Register Instructions 113 | */ 114 | 115 | // RRIT - Read Register IT 116 | public static final OpImpl ESC_x7D_RRIT = () -> { 117 | Cpu.pushLong(Cpu.IT()); 118 | }; 119 | 120 | // RRMDS - Read Register MDS 121 | public static final OpImpl ESC_x79_RRMDS = () -> { 122 | Cpu.push(Cpu.MDS >>> PrincOpsDefs.WORD_BITS); 123 | }; 124 | 125 | // RRPSB - Read Register PSB 126 | public static final OpImpl ESC_x78_RRPSB = () -> { 127 | Cpu.push(Processes.psbHandle(Cpu.PSB)); 128 | }; 129 | 130 | // RRPTC - Read Register PTC 131 | public static final OpImpl ESC_x7C_RRPTC = () -> { 132 | Cpu.push(Cpu.PTC); 133 | }; 134 | 135 | // RRWDC - Read Register WDC 136 | public static final OpImpl ESC_x7B_RRWDC = () -> { 137 | Cpu.push(Cpu.WDC); 138 | }; 139 | 140 | // RRWP - Read Register WP 141 | public static final OpImpl ESC_x7A_RRWP = () -> { 142 | Cpu.push(Cpu.WP.get()); 143 | }; 144 | 145 | // RRXTS - Read Register XTS 146 | public static final OpImpl ESC_x7E_RRXTS = () -> { 147 | Cpu.push(Cpu.XTS); 148 | }; 149 | 150 | // WRIT - Write Register IT 151 | public static final OpImpl ESC_x75_WRIT = () -> { 152 | Cpu.setIT(Cpu.popLong()); 153 | }; 154 | 155 | // WRMDS - Write Register MDS 156 | public static final OpImpl ESC_x71_WRMDS = () -> { 157 | Cpu.MDS = Cpu.pop() << PrincOpsDefs.WORD_BITS; 158 | }; 159 | 160 | // WRMP - Write Register MP 161 | public static final OpImpl ESC_x77_WRMP = () -> { 162 | Cpu.setMP(Cpu.pop()); 163 | }; 164 | 165 | // WRPSB - Write Register PSB 166 | public static final OpImpl ESC_x70_WRPSB = () -> { 167 | Cpu.PSB = Processes.psbIndex(Cpu.pop()); 168 | }; 169 | 170 | // WRPTC - Write Register PTC 171 | public static final OpImpl ESC_x74_WRPTC = () -> { 172 | Processes.resetPTC(Cpu.pop() & 0xFFFF); 173 | }; 174 | 175 | // WRWDC - Write Register WDC 176 | public static final OpImpl ESC_x73_WRWDC = () -> { 177 | Cpu.WDC = Cpu.pop(); 178 | }; 179 | 180 | // WRWP - Write Register WP 181 | public static final OpImpl ESC_x72_WRWP = () -> { 182 | Cpu.WP.set(Cpu.pop() & 0xFFFF); 183 | }; 184 | 185 | // WRXTS - Write Register XTS 186 | public static final OpImpl ESC_x76_WRXTS = () -> { 187 | Cpu.XTS = Cpu.pop() & 0xFFFF; 188 | }; 189 | 190 | } 191 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/opcodes/Ch10_Processes.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Dr. Hans-Walter Latz 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 16 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package dev.hawala.dmachine.engine.opcodes; 28 | 29 | import dev.hawala.dmachine.engine.Cpu; 30 | import dev.hawala.dmachine.engine.Mem; 31 | import dev.hawala.dmachine.engine.Opcodes.OpImpl; 32 | import dev.hawala.dmachine.engine.PrincOpsDefs; 33 | import dev.hawala.dmachine.engine.Processes; 34 | 35 | /** 36 | * Implementation of instructions defined in PrincOps 4.0 37 | * in chapter: 10 Processes 38 | * 39 | * @author Dr. Hans-Walter Latz / Berlin (2017) 40 | */ 41 | public class Ch10_Processes { 42 | 43 | /* 44 | * 10.2 Process Instructions 45 | */ 46 | 47 | /* 48 | * 10.2.1 Monitor Entry 49 | */ 50 | 51 | // ME - Monitor Entry 52 | public static final OpImpl OPC_xF1_ME = () -> { 53 | int m = Cpu.popLong(); 54 | Cpu.checkEmptyStack(); 55 | 56 | short mon = Mem.readWord(m); 57 | if (!Processes.isMonitorLocked(mon)) { 58 | mon = Processes.setMonitorLocked(mon); 59 | Mem.writeWord(m, mon); 60 | Cpu.push(PrincOpsDefs.TRUE); 61 | } else { 62 | Processes.enterFailed(m); 63 | } 64 | }; 65 | 66 | /* 67 | * 10.2.2 Monitor Exit 68 | */ 69 | 70 | // MX - Monitor Exit 71 | public static final OpImpl OPC_xF2_MX = () -> { 72 | int m = Cpu.popLong(); 73 | Cpu.checkEmptyStack(); 74 | 75 | if (Processes.exit(m)) { 76 | Processes.reschedule(false); 77 | } 78 | }; 79 | 80 | /* 81 | * 10.2.3 Monitor Wait 82 | */ 83 | 84 | // MW - Monitor Wait 85 | public static final OpImpl ESC_x02_MW = () -> { 86 | int t = Cpu.pop() & 0xFFFF; 87 | int c = Cpu.popLong(); 88 | int m = Cpu.popLong(); 89 | Cpu.checkEmptyStack(); 90 | 91 | Processes.cleanupCondition(c); 92 | 93 | boolean requeue = Processes.exit(m); 94 | short flags = Processes.fetchPSB_flags(Cpu.PSB); 95 | short cond = Mem.readWord(c); 96 | 97 | if (!Processes.isPsbFlagsAbort(flags) || !Processes.isConditionAbortable(cond)) { 98 | if (Processes.isConditionWakeup(cond)) { 99 | cond = Processes.unsetConditionWakeup(cond); 100 | Mem.writeWord(c, cond); 101 | } else { 102 | Processes.storePSB_timeout(Cpu.PSB, (t == 0) ? 0 : (short)Math.max(1, (Cpu.PTC + t) & 0xFFFF)); 103 | flags = Processes.setPsbFlagsWaiting(flags); 104 | Processes.storePSB_flags(Cpu.PSB, flags); 105 | Processes.requeue(Processes.PDA_LP_header_ready, c, Cpu.PSB); 106 | requeue = true; 107 | } 108 | } 109 | if (requeue) { 110 | Processes.reschedule(false); 111 | } 112 | }; 113 | 114 | /* 115 | * 10.2.4 Monitor Reentry 116 | */ 117 | 118 | // MR - Monitor Reentry 119 | public static final OpImpl ESC_x03_MR = () -> { 120 | int c = Cpu.popLong(); 121 | int m = Cpu.popLong(); 122 | Cpu.checkEmptyStack(); 123 | 124 | short mon = Mem.readWord(m); 125 | if (!Processes.isMonitorLocked(mon)) { 126 | Processes.cleanupCondition(c); 127 | short flags = Processes.fetchPSB_flags(Cpu.PSB); 128 | flags = Processes.setPsbFlags_cleanup(flags, Processes.PsbNull); 129 | Processes.storePSB_flags(Cpu.PSB, flags); 130 | if (Processes.isPsbFlagsAbort(flags)) { 131 | short cond = Mem.readWord(c); 132 | if (Processes.isConditionAbortable(cond)) { Cpu.processTrap(); } 133 | } 134 | mon = Processes.setMonitorLocked(mon); 135 | Mem.writeWord(m, mon); 136 | Cpu.push(PrincOpsDefs.TRUE); 137 | } else { 138 | Processes.enterFailed(m); 139 | } 140 | }; 141 | 142 | /* 143 | * 10.2.5 Notify and Broadcast 144 | */ 145 | 146 | // NC - Notify Condition 147 | public static final OpImpl ESC_x04_NC = () -> { 148 | int c = Cpu.popLong(); 149 | Cpu.checkEmptyStack(); 150 | 151 | Processes.cleanupCondition(c); 152 | short cond = Mem.readWord(c); 153 | if (Processes.getCondition_tail(cond) != Processes.PsbNull) { 154 | Processes.wakeHead(c); 155 | Processes.reschedule(false); 156 | } 157 | }; 158 | 159 | // BC - Broadcast Condition 160 | public static final OpImpl ESC_x05_BC = () -> { 161 | boolean requeue = false; 162 | int c = Cpu.popLong(); 163 | Cpu.checkEmptyStack(); 164 | 165 | Processes.cleanupCondition(c); 166 | short cond = Mem.readWord(c); 167 | while (Processes.getCondition_tail(cond) != Processes.PsbNull) { 168 | Processes.wakeHead(c); 169 | requeue = true; 170 | cond = Mem.readWord(c); 171 | } 172 | if (requeue) { 173 | Processes.reschedule(false); 174 | } 175 | }; 176 | 177 | /* 178 | * 10.2.6 Requeue 179 | */ 180 | 181 | // REQ - Requeue 182 | public static final OpImpl ESC_x06_REQ = () -> { 183 | int psbHandle = Cpu.pop(); 184 | int dstQue = Cpu.popLong(); 185 | int srcQue = Cpu.popLong(); 186 | Cpu.checkEmptyStack(); 187 | Processes.requeue(srcQue, dstQue, Processes.psbIndex(psbHandle)); 188 | Processes.reschedule(false); 189 | }; 190 | 191 | /* 192 | * 10.2.7 Set Process Priority 193 | */ 194 | 195 | // SPP - Set Process Priority 196 | public static final OpImpl ESC_x0F_SPP = () -> { 197 | int priority = Cpu.pop() & 0xFFFF; 198 | Cpu.checkEmptyStack(); 199 | 200 | short link = Processes.fetchPSB_link(Cpu.PSB); 201 | link = Processes.setPsbLink_priority(link, priority); 202 | Processes.storePSB_link(Cpu.PSB, link); 203 | Processes.requeue(Processes.PDA_LP_header_ready, Processes.PDA_LP_header_ready, Cpu.PSB); 204 | Processes.reschedule(false); 205 | }; 206 | 207 | /* 208 | * 10.4.4.3 Disabling Interrupts 209 | */ 210 | 211 | // DI - Disable Interrupts 212 | public static final OpImpl ESC_x10_DI = () -> { 213 | if (Cpu.WDC == PrincOpsDefs.WdcMax) { 214 | Cpu.interruptError(); 215 | } 216 | Processes.disableInterrupts(); 217 | }; 218 | 219 | // EI - Enable Interrupts 220 | public static final OpImpl ESC_x11_EI = () -> { 221 | if (Cpu.WDC == 0) { 222 | Cpu.interruptError(); 223 | } 224 | Processes.enableInterrupts(); 225 | }; 226 | 227 | } 228 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/opcodes/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package {@code dev.hawala.dmachine.engine.opcodes} contains the 3 | * implementation of the mesa instructions. 4 | *5 | * The instructions are automatically bound to the opcodes using the naming 6 | * convention defined by the class {@link dev.hawala.dmachine.engine.Opcodes}. 7 | *
8 | *9 | * The implementations of the instructions are grouped in classes organized along 10 | * the chapters 3 to 10 of the Mesa Processor Principles of Operation Version 11 | * 4.0 (May85) document. An additional class (for chapter "XX") holds the instructions 12 | * that became available after version 4.0 of the PrincOps (being in fact undocumented), 13 | * as far as these instructions are used. 14 | *
15 | */ 16 | package dev.hawala.dmachine.engine.opcodes; 17 | -------------------------------------------------------------------------------- /src/dev/hawala/dmachine/engine/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package {@code dev.hawala.dmachine.engine} encompasses all 3 | * components implementing the mesa engine for Dwarf. 4 | *
4 | * As for the instruction implementations, the tests are grouped by
5 | * the chapters of the PrincOps document where the instructions
6 | * are specified.
7 | *
8 | * However, there are currently no tests for the Control Transfer (chapter 9)
9 | * and Processes (chapter 10) instructions. The reason is partly laziness and
10 | * partly the fact that the environment required to test most of these instructions
11 | * (code segments, linkages, process table setups) encompasses half an OS like Pilot.
12 | *
14 | * The problem with the last point is that building that environment based on the 15 | * same assumptions used to implement the instructions will not result in an useful 16 | * test. The real test environment for testing control transfer is in fact Pilot, 17 | * So the "strategy" for these 2 chapters was to implement the instructions, review the 18 | * implementation twice in longer time intervals, correcting recognized deviations from 19 | * the PrincOps. This approach worked well for the Processes instructions (which worked 20 | * fine from the start on when booting Pilot), but however only in the second attempt 21 | * for the control transfer instructions. 22 | *
23 | */ 24 | package dev.hawala.dmachine.unittest; -------------------------------------------------------------------------------- /src/resources/base144.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devhawala/dwarf/c264af5e37f89d7aa0eec968aa23818bf5a89837/src/resources/base144.raw --------------------------------------------------------------------------------