View Javadoc

1   /***
2    * Created by IntelliJ IDEA.
3    * User: gareth
4    * Date: Sep 10, 2003
5    * Time: 10:58:14 AM
6    */
7   package com.tapina.robe.swi;
8   
9   import com.tapina.robe.runtime.*;
10  import com.tapina.robe.runtime.instruction.SWI;
11  import com.tapina.robe.swi.os.Handler;
12  import com.tapina.robe.swi.os.MemMapInfo;
13  import com.tapina.robe.swi.os.PlatformFeatures;
14  import sun.misc.CRC16;
15  
16  import java.lang.reflect.Method;
17  import java.util.Date;
18  
19  public final class OSExt extends SWIHandler {
20      private static OSExt ourInstance;
21  
22      public synchronized static OSExt getInstance() {
23          if (ourInstance == null) {
24              ourInstance = new OSExt();
25          }
26          return ourInstance;
27      }
28  
29      private OSExt() {
30      }
31  
32      public static int getBase() {
33          return 0x40;
34      }
35  
36      private static final String[] methodNames = new String[] {
37          "ChangeEnvironment", "", "ReadMonotonicTime", "", "", "", "", "", // 0x40
38          "WriteEnv", "", "", "", "", "", "", "", // 0x48
39          "", "ReadMemMapInfo", "", "", "", "", "", "", // 0x50
40          "", "", "", "CRC", "", "", "", "", // 0x58
41          "", "", "", "", "", "ScreenMode", "DynamicArea", "", // 0x60
42          "", "", "", "", "", "PlatformFeatures", "", "", // 0x68
43          "", "CallASWIR12", "", "", "", "", "", "", // 0x70
44          "", "", "", "", "", "", "", "" // 0x78
45      };
46  
47      public static Method getMethod(Integer offset) throws NoSuchMethodException {
48          return getMethod(methodNames[offset.intValue()]);
49      }
50  
51      private static final Method getMethod(String name) throws NoSuchMethodException {
52          return OSExt.class.getMethod(name, METHOD_PARAMETERS);
53      }
54  
55      public final void ChangeEnvironment(Environment env) {
56          final int R[] = env.getCpu().R;
57          Handler oldHandler = getEnvironmentHandler(R[0]);
58          if (R[1] != 0 || R[3] != 0) {
59              log.warning("We do not support changing the environment in OS.ChangeEnvironment");
60          }
61          R[1] = oldHandler.getAddress();
62          R[2] = oldHandler.getR12();
63          R[3] = oldHandler.getBuffer();
64      }
65  
66      static final Handler DEFAULT_APPSPACE_HANDLER = new Handler(OS.DEFAULT_RAM_LIMIT, 0, 0);
67  
68      public final Handler getEnvironmentHandler(int handlerNumber) {
69          switch (handlerNumber) {
70              case 14:
71                  return DEFAULT_APPSPACE_HANDLER;
72              default:
73                  throw new SWIError(0, "Unknown OS.ChangeEnvironment " + handlerNumber);
74          }
75      }
76  
77      /***
78       * Number of centi-seconds since last hard reset.
79       * @param env OUT: R0 = Number of centi-seconds since last hard reset.
80       */
81      public final void ReadMonotonicTime(Environment env) {
82          env.getCpu().R[0] = readMonotonicTime();
83      }
84  
85      /***
86       * Number of centi-seconds since program start.
87       * @return Number of centi-seconds since program start.
88       */
89      public final int readMonotonicTime() {
90          return (int) ((System.currentTimeMillis() - OS.DEFAULT_APP_ENVIRONMENT.getStartTime().getTime()) / 10);
91      }
92  
93      public final void WriteEnv(Environment env) {
94          final int R[] = env.getCpu().R;
95          String commandLine = env.getMemoryMap().getString0(R[0]);
96          long fiveByteTime = env.getMemoryMap().getWord(R[1]);
97          fiveByteTime |= ((long) env.getMemoryMap().getByte(R[1] + 4)) << 32;
98          Date startTime = OS.convertToDate(fiveByteTime);
99          writeEnv(commandLine, startTime);
100     }
101 
102     public final void writeEnv(String commandLine, Date startTime) {
103         OS.DEFAULT_APP_ENVIRONMENT.setCommandLine(commandLine);
104         OS.DEFAULT_APP_ENVIRONMENT.setStartTime(startTime);
105     }
106 
107     private final static MemMapInfo DEFAULT_MEM_MAP_INFO = new MemMapInfo(4096, 4096); // 16MB machine
108 
109     public final void ReadMemMapInfo(Environment env) {
110         final int[] R = env.getCpu().R;
111         MemMapInfo memMapInfo = readMemMapInfo();
112         R[0] = memMapInfo.getPageSize();
113         R[1] = memMapInfo.getNumberOfPages();
114     }
115 
116     public final MemMapInfo readMemMapInfo() {
117         return DEFAULT_MEM_MAP_INFO;
118     }
119 
120     public final void CRC(Environment env) {
121         final int[] R = env.getCpu().R;
122         final ByteArray data = env.getMemoryMap().getByteArray(R[1], R[2] - R[1], false);
123         if ((R[2] - R[1]) % R[3] != 0) {
124             throw new SWIError(0, "End address never reached using specified increment");
125         }
126         R[0] = crc((short) R[0], data, R[3]);
127     }
128 
129     public final short crc(short crc, ByteArray data, int increment) {
130         CRC16 crc16 = new CRC16();
131         crc16.value = crc;
132         for (int i = 0; i < data.getLength(); i += increment) {
133             byte b = data.getByte(i);
134             crc16.update(b);
135         }
136         return (short) crc16.value;
137     }
138 
139     /***
140      * This call is used to change or read the screen mode. 
141      * See also Wimp_SetMode.
142      * @param env IN: R0 = reason code, other registers dependant on call.
143      */
144     public final void ScreenMode(Environment env) {
145         final int[] R = env.getCpu().R;
146         final int reasonCode = R[0];
147         switch (reasonCode) {
148             case 1:
149                 R[1] = getScreenMode();
150                 break;
151             default:
152                 throw new SWIError(0, "Unknown OS.ScreenMode " + reasonCode);
153         }
154     }
155 
156     public final int getScreenMode() {
157         log.warning("Always returns screen mode as Mode 21");
158         return 21;
159     }
160 
161     public final void DynamicArea(Environment env) {
162         final int[] R = env.getCpu().R;
163         final MemoryMap memoryMap = env.getMemoryMap();
164         switch (R[0]) {
165             case 0:
166                 DynamicArea newArea = memoryMap.createDynamicArea(R[2], R[5], R[6], R[7], memoryMap.getString0(R[8]),
167                                                                   R[4] & 3, R[4] & (~3));
168                 R[1] = newArea.getAreaNumber();
169                 R[3] = newArea.getBase();
170                 R[5] = newArea.getMaximumSize();
171                 break;
172             case 2:
173                 final int areaNumber = R[1];
174                 DynamicArea area = memoryMap.findDynamicArea(areaNumber);
175                 R[2] = area.getSize();
176                 R[3] = area.getAddress();
177                 R[4] = area.getFlags();
178                 R[5] = area.getMaximumSize();
179                 R[6] = area.getHandlerRoutine();
180                 R[7] = area.getHandlerWorkspace();
181                 final String name = area.getName();
182                 final RawDataBlock nameBlock = memoryMap.createSystemDataBlock(name);
183                 R[8] = nameBlock.getAddress();
184                 break;
185             default:
186                 throw new SWIError(0, "We do not support OS.DynamicArea " + R[0]);
187         }
188     }
189 
190     private final static PlatformFeatures DEFAULT_PLATFORM_FEATURES = new PlatformFeatures(
191             PlatformFeatures.CODE_SYNCHRONISATION_REQUIRED |
192             PlatformFeatures.PC_PLUS_8_STORED
193     );
194 
195     public final void PlatformFeatures(Environment env) {
196         final int[] R = env.getCpu().R;
197         R[0] = getPlatformFeatures().getCodeFeatures();
198     }
199 
200     public final PlatformFeatures getPlatformFeatures() {
201         return DEFAULT_PLATFORM_FEATURES;
202     }
203 
204     public final void CallASWIR12(Environment env) {
205         try {
206             new SWI(Condition.AL, env.getCpu().R[12]).checkAndExecute(env);
207         } catch (UnknownSWIException e) {
208             throw new SWIError(0, e);
209         }
210     }
211 }
212