/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.ide.ui.views; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.util.Collections; import java.util.Iterator; import java.util.List; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import de.codesourcery.jasm16.Address; import de.codesourcery.jasm16.Size; import de.codesourcery.jasm16.WordAddress; import de.codesourcery.jasm16.emulator.EmulationListener; import de.codesourcery.jasm16.emulator.IEmulationListener; import de.codesourcery.jasm16.emulator.IEmulator; import de.codesourcery.jasm16.emulator.memory.MemUtils; import de.codesourcery.jasm16.utils.Misc; public class StackView extends AbstractView { public static final String VIEW_ID = "stack-view"; private JPanel panel; private final JTextArea textArea = new JTextArea(); private IEmulator emulator; private int numberOfWordsToDump = 16; private boolean printASCII = true; private final IEmulationListener listener = new EmulationListener() { @Override public void afterCommandExecution(IEmulator emulator, int commandDuration) { if ( ! isFullSpeedMode() ) { refreshDisplay(); } } @Override public void afterReset(IEmulator emulator) { if ( ! isFullSpeedMode() ) { refreshDisplay(); } } @Override public void afterMemoryLoad(IEmulator emulator, Address startAddress, int lengthInBytes) { if ( ! isFullSpeedMode() ) { refreshDisplay(); } } @Override public void onStopHook(IEmulator emulator, Address previousPC, Throwable emulationError) { refreshDisplay(); } }; public StackView(IEmulator emulator) { setEmulator( emulator ); } public StackView() { } @Override public void refreshDisplay() { if ( emulator == null ) { return; } Address startOfStack = emulator.getCPU().getSP(); final int realStart = (startOfStack.toWordAddress().getValue() - numberOfWordsToDump + 1 ) & 0xffff; final byte[] data = MemUtils.getBytes( emulator.getMemory() , Address.wordAddress( realStart ) , Size.words( numberOfWordsToDump) , true ); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { final List<String> lines = Misc.toHexDumpLines( Address.wordAddress( realStart ), data, data.length , 1 , printASCII , true , true ); Collections.reverse( lines ); // reverse lines => print stack from highest to lowest address Address current = Address.wordAddress( ( realStart + numberOfWordsToDump -1 ) & 0xffff ); StringBuilder result = new StringBuilder(); for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) { String line = iterator.next(); result.append( line ); if ( current.equals( emulator.getCPU().getSP() ) ) { result.append(" << "); } if ( iterator.hasNext() ) { result.append("\n"); } current = current.decrementByOne(); } textArea.setText( result.toString() ); } }); } public void setEmulator(IEmulator emulator) { if (emulator == null) { throw new IllegalArgumentException("emulator must not be NULL."); } if ( this.emulator == emulator ) { return; } if ( this.emulator != null ) { this.emulator.removeEmulationListener( listener ); } this.emulator = emulator; emulator.addEmulationListener( listener ); } @Override public void disposeHook() { if ( this.emulator != null ) { this.emulator.removeEmulationListener( listener ); this.emulator = null; } } protected JPanel createPanel() { textArea.setEditable( false ); setColors( textArea ); textArea.setFont( getMonospacedFont() ); textArea.setEditable( false ); final JPanel panel = new JPanel(); setColors( panel ); panel.setLayout( new GridBagLayout() ); final GridBagConstraints cnstrs = constraints( 0 , 0 , true , true , GridBagConstraints.BOTH ); panel.add( textArea , cnstrs ); return panel; } @Override public JPanel getPanel() { if ( panel == null ) { panel = createPanel(); } return panel; } @Override public String getTitle() { return "stack view"; } @Override public String getID() { return VIEW_ID; } }