View Javadoc

1   package com.tapina.robe.swi.os;
2   
3   import com.tapina.robe.runtime.ByteArrayUtils;
4   import com.tapina.robe.runtime.DataBlock;
5   import com.tapina.robe.swi.SWIError;
6   
7   import java.io.File;
8   import java.io.FileInputStream;
9   import java.io.IOException;
10  import java.util.HashMap;
11  import java.util.LinkedList;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.logging.Logger;
15  
16  /***
17   * Created by IntelliJ IDEA.
18   * User: gareth
19   * Date: Sep 8, 2003
20   * Time: 9:18:36 AM
21   */
22  public final class SpriteArea extends DataBlock {
23      private static final int SIZE_OFFSET = 0;
24      private static final int SPRITE_COUNT_OFFSET = 4;
25      private static final int SPRITE_OFFSET = 8;
26      private static final int FREE_SPACE_OFFSET = 12;
27  
28      private final Logger log = Logger.getLogger(getClass().getName());
29      private final List spriteList = new LinkedList();
30      private final Map spriteMap = new HashMap(30);
31      private byte[] data;
32      int size;
33  
34      public SpriteArea(int address) {
35          super(address);
36          size = 16;
37          data = new byte[16];
38          ByteArrayUtils.putInt(data, SPRITE_OFFSET, 16);
39          ByteArrayUtils.putInt(data, FREE_SPACE_OFFSET, 16);
40      }
41  
42      public SpriteArea(DataBlock dataBlock) {
43          super(dataBlock.getAddress());
44          // First 4 words are size, number of sprites, sprite offset and free space offset
45          log.warning("Creating SpriteArea from existing DataBlock, existing data will be ignored");
46          size = dataBlock.getSize();
47          data = new byte[size];
48          System.arraycopy(dataBlock.getBytes(), 0, data, 0, size);
49      }
50  
51      public byte[] getBytes() {
52          return data;
53      }
54  
55      public final void addSprite(Sprite sprite) {
56          spriteList.add(sprite);
57          spriteMap.put(sprite.getName().toLowerCase(), sprite);
58          ByteArrayUtils.putInt(data, SPRITE_COUNT_OFFSET, spriteList.size());
59          final int freeSpace = ByteArrayUtils.getInt(data, FREE_SPACE_OFFSET);
60          if (this.data.length < freeSpace + sprite.data.length) {
61              log.warning("Extending sprite area automatically, this doesn't normally happen");
62              setSize(size + sprite.data.length);
63          }
64          System.arraycopy(sprite.data, 0, this.data, freeSpace, sprite.data.length);
65          ByteArrayUtils.putInt(data, FREE_SPACE_OFFSET, freeSpace + sprite.data.length);
66      }
67  
68      public final int getSize() {
69          return size;
70      }
71  
72      public void setSize(int newSize) {
73          byte[] newBytes = new byte[newSize];
74          System.arraycopy(data, 0, newBytes, 0, newSize < size ? newSize : size);
75          this.size = newSize;
76          this.data = newBytes;
77          ByteArrayUtils.putInt(data, SIZE_OFFSET, size);
78      }
79  
80      public final Sprite getSprite(String name) {
81          return (Sprite) spriteMap.get(name.toLowerCase());
82      }
83  
84      public final void merge(File spriteFile) {
85          if (!spriteList.isEmpty()) {
86              log.warning("Merge of sprite files into sprite areas not supported - replacing");
87          }
88          load(spriteFile);
89      }
90  
91      public final void load(File spriteFile) {
92          final int size = (int) spriteFile.length();
93          byte[] data = new byte[16];
94          ByteArrayUtils.putInt(data, 0, size);
95          FileInputStream in = null;
96          try {
97              in = new FileInputStream(spriteFile);
98              in.read(data, 4, 12);
99              int offset = ByteArrayUtils.getInt(data, SPRITE_OFFSET) - 16;
100             in.skip(offset);
101             for (int spriteCount = ByteArrayUtils.getInt(data, 4); spriteCount > 0; spriteCount--) {
102                 in.read(data, 0, 4);
103                 final int spriteSize = ByteArrayUtils.getInt(data, 0);
104                 final byte[] spriteData = new byte[spriteSize];
105                 in.read(spriteData, 4, spriteSize - 4);
106                 addSprite(new Sprite(spriteData));
107             }
108         } catch (IOException e) {
109             throw new SWIError(0, e);
110         } finally {
111             if (in != null) {
112                 try {
113                     in.close();
114                 } catch (IOException e) {
115                     throw new SWIError(0, e);
116                 }
117             }
118         }
119     }
120 
121 }