View Javadoc

1   /*
2    * $Id: PrintLiteralInstruction.java,v 1.5 2005/10/24 16:04:43 weiju Exp $
3    * 
4    * Created on 06.10.2005
5    * Copyright 2005 by Wei-ju Wu
6    *
7    * This file is part of The Z-machine Preservation Project (ZMPP).
8    *
9    * ZMPP is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as published by
11   * the Free Software Foundation; either version 2 of the License, or
12   * (at your option) any later version.
13   *
14   * ZMPP is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with ZMPP; if not, write to the Free Software
21   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22   */
23  package org.zmpp.vm;
24  
25  import org.zmpp.base.MemoryReadAccess;
26  
27  /***
28   * This class implements the print and print_ret instructions.
29   * 
30   * @author Wei-ju Wu
31   * @version 1.0
32   */
33  public class PrintLiteralInstruction extends AbstractInstruction {
34  
35    public static final int OP_PRINT              = 0x02;
36    public static final int OP_PRINT_RET          = 0x03;
37    
38    /***
39     * The instruction address.
40     */
41    private int instructionAddress;
42    
43    /***
44     * Memory access object.
45     */
46    private MemoryReadAccess memaccess;
47    
48    /***
49     * Constructor.
50     * 
51     * @param machineState the machine state reference
52     * @param opcode the opcode
53     * @param memaccess the memory access object
54     * @param instrAddress the instruction address
55     */
56    public PrintLiteralInstruction(Machine machineState, int opcode,
57        MemoryReadAccess memaccess, int instrAddress) {
58      
59      super(machineState, opcode);
60      
61      this.memaccess = memaccess;
62      instructionAddress = instrAddress;
63    }
64    
65    /***
66     * {@inheritDoc}
67     */
68    public InstructionForm getInstructionForm() {
69      
70      return InstructionForm.SHORT;
71    }
72  
73    /***
74     * {@inheritDoc}
75     */
76    public OperandCount getOperandCount() {
77      
78      return OperandCount.C0OP;
79    }
80    
81    /***
82     * {@inheritDoc}
83     */
84    public void setLength(int length) {
85  
86      // overridden to do nothing
87    }
88    
89    /***
90     * {@inheritDoc}
91     */
92    public int getLength() {
93      
94      return getLiteralLengthInBytes() + 1;
95    }
96  
97    /***
98     * {@inheritDoc}
99     */
100   public void execute() {
101 
102     getMachine().printZsciiString(instructionAddress + 1);
103     if (getOpcode() == OP_PRINT_RET) {
104       
105       returnFromRoutine(TRUE);
106       
107     } else if (getOpcode() == OP_PRINT) {
108       
109       nextInstruction();
110       
111     } else {
112      
113       throwInvalidOpcode();
114     }    
115   }
116   
117   /***
118    * Returns the address of the literal.
119    * 
120    * @return the address of the literal
121    */
122   public int getLiteralAddress() {
123     
124     return instructionAddress + 1;
125   }
126 
127   /***
128    * Determines the byte length of the ZSCII string literal.
129    *  
130    * @return the length of the literal in bytes
131    */
132   private int getLiteralLengthInBytes() {
133     
134     int currentAddress = instructionAddress + 1;
135     int zword = 0;
136     
137     do {
138       
139       zword = memaccess.readUnsignedShort(currentAddress);
140       currentAddress += 2;
141       
142     } while ((zword & 0x8000) == 0);
143     
144     return currentAddress - (instructionAddress + 1);
145   }
146 }