CPCWiki forum

General Category => Programming => Topic started by: EgoTrip on 23:51, 24 February 16

Title: [cpctelera]Bit Arrays
Post by: EgoTrip on 23:51, 24 February 16
How do I use bit arrays? The example isn't very useful and I can't figure it out.

What I want to do is convert my level data so each byte stores two tiles instead of one. This way I can halve the memory I am currently using (10240 bytes) and then I will hopefully have enough space left over to finish the game.
Title: Re: [cpctelera]Bit Arrays
Post by: Munchausen on 08:44, 25 February 16
Is it just C?

I guess you want to work with nibbles (units of 4 bits in length)? Why don't you just use an unsigned char and masks? This would give you more control over the generated code. Otherwise, you can do something like

struct A {
  unsigned int nibble1 : 4;
  unsigned int nibble2 : 4;
}


or

union A {
  struct B {
    unsigned int nibble1 : 4;
    unsigned int nibble2 : 4;
  };
  unsigned char byte;
}
Title: Re: [cpctelera]Bit Arrays
Post by: arnoldemu on 08:58, 25 February 16
Quote from: EgoTrip on 23:51, 24 February 16
How do I use bit arrays? The example isn't very useful and I can't figure it out.

What I want to do is convert my level data so each byte stores two tiles instead of one. This way I can halve the memory I am currently using (10240 bytes) and then I will hopefully have enough space left over to finish the game.
This may sound stupid, but how many tiles do you have?
If you have less than or exactly 16 then you can store more than 1 in a byte, more than 16 and you can only store 1.
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 10:33, 25 February 16
@Munchausen (http://www.cpcwiki.eu/forum/index.php?action=profile;u=792) I am using CPCtelera and there are Bit Array functions which I assume are what I need to use.

@arnoldemu (http://www.cpcwiki.eu/forum/index.php?action=profile;u=122)  Theres more than 16. Cant remember off the top of my head but theres at least 40 different tiles and tile types.

Surely its possible to store two, if there are less than 128, one in the first 4 bits and the other in the second. I assume the CPCtelera bit array functions cater for this, for 1 2 and 4 bits storing values. I think I understand it in principle. I just don't understand how to use it. My maths brain isn't very good remember.

Heres's an example level:


    0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12,
    0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
    0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x13,
    0x17, 0x24, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
    0x17, 0x24, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00,
    0x17, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x1B, 0x1A, 0x00, 0x00, 0x00, 0x13,
    0x17, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
    0x17, 0x24, 0x24, 0x24, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x13,
    0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
    0x16, 0x15, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x14


So am I right in understanding that you could combine two tiles into one, so the first two are 0x10 and 0x11. If the first tile 0 uses the first 4 bits (0-0x7f) then the second tile would use the second 4 bits (0x80-0xFF)which would increase its value to 0x91 by adding 0x80? Then add the two together to give the encoded byte 0xA1?

I need to figure out how to automate it too, because encoding by hand is going to be a labourious task. I could probably do that in BASIC and output to the printer or and ASCII file in WinAPE. Decoding it in C is a whole other matter and thats where I'm completely lost.

In fact none of the tiles go above 0x3F so could I even encode four in each byte?
Title: Re: [cpctelera]Bit Arrays
Post by: arnoldemu on 10:38, 25 February 16
Quote from: EgoTrip on 10:33, 25 February 16
@arnoldemu (http://www.cpcwiki.eu/forum/index.php?action=profile;u=122)  Theres more than 16. Cant remember off the top of my head but theres at least 40 different tiles and tile types.
4 bits gives a max of 16. So you can't use less than a byte. Sorry. So this means some bits are unused but not much you can do about that.

1 bit gives max of 2,
2 bits gives a max of 4,
3 bits gives a max of 8,
4 bits a max of 16,
5 bits a max of 32.
6 bits a max of 64.
7 bits a max of 128.
8 bits a max of 256.

Say you have a max of 32, there is 3 bits unused in one byte UNLESS two/three bytes are put together. Now you can reduce the waste but how you access the data is more complex.

Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 10:58, 25 February 16
OK so is there any other way of compressing that data? RLE is too confusing and won't really reclaim much memory anyway. Otherwise the game will be impossible to finish.
Title: Re: [cpctelera]Bit Arrays
Post by: gerald on 11:24, 25 February 16
Quote from: EgoTrip on 10:58, 25 February 16
OK so is there any other way of compressing that data? RLE is too confusing and won't really reclaim much memory anyway. Otherwise the game will be impossible to finish.
RLE is one method, you can also use procedural generation.
On the level you posted, you have a border. If this border is there on all level, just add a function to generate it. For the opening in it, just store their location and 'open' them once the border is generated.
You can also have functions for drawing lines of the same tiles (0x24 in your level). One function for vertical,  one for horizontal. may be one for rectangle.

Since you level is 16*10, you can store coordinate in one byte, so where you have 5 consecutive tiles, you can compress them as 2/3 bytes ( xxxxyyyy lllttttt)
2 bytes if you use a table of line
3 bytes if you use a byte to specify the line type
Title: Re: [cpctelera]Bit Arrays
Post by: Munchausen on 11:58, 25 February 16
You could store 4 tiles in 3 bytes as long as you have less than 64 tiles, but it is going to slow you down doing a lot of bit manipulating. Gerald's idea sounds better.
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 14:10, 25 February 16
Hi @EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) ,
   as @arnoldemu (http://www.cpcwiki.eu/forum/index.php?action=profile;u=122) and others have already pointer out, there is no way to store 40 values on 4 bits. 4 bits give you at most 2^4 = 16 values. The only thing you could do for this is ensuring that you have only 16 different tiles per screen. You could have 40 tiles for your complete game, but never use more than 16 per screen (or on most of your screens, and have a special treatment for screens having more than 16 tiles). Other more complex possibilities will include using 16 tiles for the upper part of the screen and 16 for the lower... You could think of different combinations, but with 4 bits you can only address 16 different values at the same time.
   
   Now, let's explain how bitarrays work.


   To store 2 values into each single byte, you have cpct_set4Bits (http://lronaldo.github.io/cpctelera/files/bitarray/cpct_set4Bits-asm.html) and cpct_get4Bits (http://lronaldo.github.io/cpctelera/files/bitarray/cpct_get4Bits-asm.html). This 2 functions let you read and store values into the bitarray. So, let's imagine we wanted to store a 10x10 tiles screen into a bitarray, having 2 tiles per byte. We will need 50 bytes for that (10x10 = 100 tiles, 100/2 = 50 bytes, as we store 2 tiles per byte). We define a normal array to store our values:

   const u8 map[50];  // 10 * 10 / 2

   Let's imagine tile 0 as a void space and tile 1 as a wall. We can some loops to create a frame with walls (fill the 4 borders of the map with walls):

   // Fill in the upper and lower borders.
   // First line of the map= 10 first tiles, last line = 10 last tiles
   //----------------------------------------------------------------------------------
   for(i=0; i < 10; i++) {
      cpct_set4Bits(map, 1, i);      // This is equivalent to map[i] = 1;
      cpct_set4Bits(map, 1, i + 90); // This is equivalent to map[90 + i] = 1; Remember that our 4-bits map is 10x10 = 100 tiles.
   }

   // Fill in the left and right borders.
   // Left border = first tile of every line = {0, 10, 20...}
   // Right border = last tile of every line = {9, 19, 29...} (+9)
   // Take into account that 0, 9, 90 and 99 are already set
   //----------------------------------------------------------------------------------
   for(i=10; i < 90; i+=10) {
      cpct_set4Bits(map, 1, i);     // Left tile
      cpct_set4Bits(map, 1, i + 9); // Right tile
   }

   Now, let's create a function to draw the map in the screen.

   void drawTheMap() {
      u8 x, y, i;


      // 'i' will be the index of the next tile in the map
      i=0; 
      for(y=0;y<10;y++) {
         for(x=0;x<10;x++) {
            u8 tile = cpct_get4Bits(map, i); // equivalent to tile=map[i];
            drawNextTile(tile);              // This imaginarily draws a tile and stays ready for next one to the right
            i++;                             // Next tile from the map
         }
         jumpToNextTileLine(); // This imaginary function sets everything ready for drawing next tile line
      }
   }

   Another way to populate a bitarray is doing it at the same time it is defined. For doing this you have to take into account the way it works. In this example, we want to use 4-bits for each tile. 4-bits is a nibble, and corresponds to 1 hexadecimal digit. So, we can initialize our map using hexadecimal numbers, taking into account that each digit will be the value of a tile. It will be like this:

   // 0x is the prefix for hexadecimal numbers. We use a define for getting rid of it visually
   // For this example, 0=space, 15=wall_type1, 10_wall_type2, 1=door, 2=enemy respawn, 3=weapon respawn
   //------------------------------------------------------------------------
   #define _ 0x
   const u8 map[50] = {
      _FF,_FF,_FF,_FF,_FF,
      _F0,_00,_00,_00,_3F,
      _F0,_AA,_20,_AA,_0F,
      _F0,_AA,_A1,_AA,_0F,
      _F0,_00,_00,_00,_0F,
      _F0,_AA,_1A,_AA,_0F,
      _F0,_AA,_00,_AA,_0F,
      _F0,_00,_00,_A2,_0F,
      _F0,_3A,_00,_00,_0F,
      _FF,_FF,_FF,_FF,_FF
   };
   #undef _

   To better view this map, I have created a PNG with some random tiles. The right part of the image is the same map, both with non-zero values overlayed to note their meaning.
   [attachimg=1]
   I hope this works as an example on how bitarrays work.
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 14:22, 25 February 16
My original confusion was obviously how binary worked. I was thinking you could chop it in half but it doesn't work that was as its not linear.

Theres no easy way of doing this which doesn't involve a complete re-write and redoing the screens is there? Ideally I'd like to do something with the data that RGAS puts out as I really cant be doing with having to do it all over again in some other program or way.
Title: Re: [cpctelera]Bit Arrays
Post by: andycadley on 15:35, 25 February 16
I suspect the trick will be to store your screens compressed, then expand the current one into your current easy to use array as you need it. Pretty sure we can help come up with something if you post an example of a screen layout.

Also 100% certain we can transform whatever your current data is into whatever it needs be in a nice automated way.  ;)
Title: Re: [cpctelera]Bit Arrays
Post by: Sykobee (Briggsy) on 15:41, 25 February 16
An awkward situation - do you have an example screen that we can see?


There are some tricks - your map can store tile type rather than tile graphic. For example, if you have several wall blocks for corners, straights, etc, then you can algorithmically calculate these on the fly from a single wall block in the map data depending upon what is around it. Ditto for most things with borders - water, paths, etc. All you'd need to do is get the number of tile types to 16.


But special objects (collectables) may be a problem - they're all different. But they share a type - special object, use that, and have a few bytes after each screen's tile type data to specify the special object's actual specific object type (in the order they appear on the screen).


Yes, these methods stop you being able to use the map designer's tools, sorry.
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 18:40, 25 February 16
Attached are some screen shots. As you can see, there is nothing uniform about any of them so some tricks are going to be unusable.

I already have special objects seperate from the map, it was necessary to do it this way as none of them were persistent, they disappeared forever once collected and if I changed them on the map then it would change them forever even after a game over then restart. This is one problem I have solved and it works great.
Title: Re: [cpctelera]Bit Arrays
Post by: andycadley on 21:56, 25 February 16
Quote from: EgoTrip on 10:33, 25 February 16Heres's an example level:


    0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12,
    0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
    0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x13,

...

Ok, so let's start with the worlds easiest version of RLE possible. Not particularly efficient, or clever and easily beatable once you get your head around it. What we'll do is store our levels in pairs of bytes. The first byte of each pair tells us how many bytes to write into our level array, the second which value to write. So the first three lines of your screen (as quoted) encoded into pairs would look something like:

(1,0x10), (14,0x11), (1,0x12),     
(1,0x17), (5,0x00), (3,0x24), (6,0x00), (1,0x13),   
(1,0x17), (7,0x00), (1,0x24), (1,0x0e), (2,0x00), (1,0x0e), (2,0x00), (1,0x13),

That's got our size down from 48 bytes to 32, a 30% saving without really trying very hard.

The pseudo code to expand this would look something like:


x =0
y =0

while y < heightofscreen
  read count and tile
  while count > 0
     screen(x,y) = tile
     x = x + 1
     if (x > widthofscreen) then x = 0, y = y + 1
  end while
end while


We can be a lot smarter than that if we start looking closer at the data. For example if all our tiles are numbered less than 128, we can use count values less than 128 to mean "just write one of these tiles out" and values of 128 and above to mean (128 + real count value). That would avoid the overhead of encoding single tiles with the byte pair (1, xxx) as above so will pack data tighter. That's "step 2" though, after getting your head around how the easiest encoding pattern would work.
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 22:14, 25 February 16
QuoteWe can be a lot smarter than that if we start looking closer at the data. For example if all our tiles are numbered less than 128, we can use count values less than 128 to mean "just write one of these tiles out" and values of 128 and above to mean (128 + real count value). That would avoid the overhead of encoding single tiles with the byte pair (1, xxx) as above so will pack data tighter. That's "step 2" though, after getting your head around how the easiest encoding pattern would work.

Which would be:

x10,x8E,x11,x12,
x17,x85,x00,x83,x24,x86,x00,x13
x17,x87,x00,x24,x0e,x82,x00,x13

Thats 20 Bytes instead of 48. 

And may I suggest another First Byte that statest "I am  compressed" (lets say x80) and "I am uncompressed" (x00).

I think your first Level would be better of beeing uncompressed.

// handling compressed screen

x =0
y =0

while y < heightofscreen
  read data;
  if data < x81  then screen(x,y) = data
  else
   {
    count = data - 0x80;
    read tile;
    while count > 0
     screen(x,y) = tile
     x++
     if (x > widthofscreen) then x = 0, y++
    count--
  end while // count
  }
end while  // y

Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 22:40, 25 February 16
   I was writting a post with 2 encoding ideas, being one of them a simple RLE encoding, just like @andycadley (http://www.cpcwiki.eu/forum/index.php?action=profile;u=327) has suggested. In fact, I was going to suggest the approach of using tile identifiers greater than a value (be it 128, 64 or whatever) as "commands" for repeating. In fact, you could think of them as "commands" in the broader sense to do things, and write a parser for them. Let's take your 3-houses map, for instance, and encode one similar to it. Imagine your first line of the map to be this one:
   
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,

   Let's define that a value greater than 128 in your array means exactly this "repeat this-128 times the next tile". That let's us encode previous line as this:

   128+38, 0, 1, 2

   We could do the same with a line encoding the upper side of your 3 houses (without vegetation):

   0,0,0,0,4,4,4,4,4,4,0,0,0,0,0,4,4,4,4,4,4,0,0,0,0,0,4,4,4,4,4,4,0,0,0,0,0,0,1,2,

   It will be like this,

   128+4, 0,   128+6, 4,   128+5, 0,   128+6, 4,   128+5, 0,   128+6, 4,   128+6, 0,   1, 2,

   To improve readability, we could create a macro

   // Macro for inserting repetitions encoded in our "manual RLE"
   #define R(Num,Value)  (128+Num), (Value)
   ....
   const u8 map[] = { .....
   ....
   R(4, 0), R(6, 4), R(5, 0), R(6, 4), R(5, 0), R(6, 4), R(6, 0), 1, 2,
   ....

   Now it is easy to read "Repeat 4 times 0", "Repeat 6 times 4".


   The only thing left is creating a function that transforms this encoding into a byte-by-byte one, to use it for the screen that is to be drawn. We could do it as follows:

   // Maximum value for a tile. Anything greater than that will be
   // considered a command in the encoded map
   #define MAX_TILE  128
   
   const u8 vis_map[20*20];   // Visible map. The one that will be drawn to screen


   // Decompresses an encoded map into a byte-by-byte one
   void decompress_map(u8* encoded_map) {
      u16 i = 0, e = 0;       // Indexes for the map arrays (they will be greater than 256)


       // Repeat until vis_map is complete
      while(i < 20*20) {
         u8 c = encoded_map[e];  // Get next value from encoded_map
         e++;                    // Point to the next value in the encoded map


         // Check if value got is a command or a tile-id
         if (c <= MAX_TILE) {
            // c is a tile-id, we only have to copy it to the visible map and
            // Point to the next value to be inserted in the visible map
            vis_map[i] = c;
            i++;
         } else {
            // c is a command. Get next value as tile-id and point to the next value in encoded_map
            u8 r, tile = encoded_map[e];
            e++;


            // Insert tile in visible_map (c - MAX_TILE) times
            for(r=0; r < (c - MAX_TILE); r++) {
               vis_map[i] = tile;     // Insert tile in the next visible_map location
               i++;                       // Point to the next visible_map location
            }
         }
      }
   }

   
   With this, and the examples that @andycadley (http://www.cpcwiki.eu/forum/index.php?action=profile;u=327) and @SRS (http://www.cpcwiki.eu/forum/index.php?action=profile;u=805) have given, you have an introduccion on how to encode your maps to save space with a manual RLE.


   As I mentioned earlier, you can develop this technique much more thinking of your values greater than MAX_TILE as commands. For instance, you could create commands like "Repeat next complete line N times" for maps where you have 5 or 6 lines that are identical, like your second one. However, I suggest starting first with a basic encoding, grasp it fully and then advance one step at a time.
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 22:53, 25 February 16
@ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227) - thats a good explanation and suggestion.

@EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) - if you want automatic encoding instead of doing it all manual for your levels rosetta may help: "Run-length encoding - Rosetta Code (http://www.rosettacode.org/wiki/Run-length_encoding#C"); - it uses the <128 >128 method

And, btw: nice, "nintendo-style" gfx !
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 15:21, 26 February 16
I give up.  Consider this project abandoned.
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 18:18, 26 February 16
Quote from: EgoTrip on 15:21, 26 February 16
I give up.  Consider this project abandoned.

;) - nice try. As others said  - if you need help, even coding that, we are here ! Maybe you can put it on GitHub for shared work.
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 18:30, 26 February 16
I tried an easy solution :
cpc_UnExo(dataLevelCompress, currentLevel);

That all !

Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 18:32, 26 February 16
This isnt the only reason I have given up. I keep encountering bugs that I can't fix and appear for no apparent reason, its stressing me out and im not having any fun doing this so whats the point.
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 18:43, 26 February 16
Okay, that is an issue no more fun - this all is a hobby, and hobby without fun, no way.

     You could release your work into public so someone could have a look, get it in shape and so on. Just maybe, so all your work does not get lost.
Title: Re: [cpctelera]Bit Arrays
Post by: reidrac on 18:43, 26 February 16
@ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227) Very nice examples, it is similar to what I've done in some projects.

I recommended @EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) to use an existing RLE compressor (like ZX7 by Einair Saukas) and compress all maps data, and use a "working" version of each screen so he can uncompress to that memory address before rendering the map. ZX7 has a compressor that can be run in a regular PC and Z80 ASM code to be used in the CPC.

Map data usually contains repeating patterns that compress OK with a good RLE compressor.

For example, I use UCL (from UPX fame) in Space Pest Control and this is what I get for the 25 screens:


ucl: 100 bytes compressed into 57 bytes
ucl: 100 bytes compressed into 58 bytes
ucl: 100 bytes compressed into 53 bytes
ucl: 100 bytes compressed into 54 bytes
ucl: 100 bytes compressed into 46 bytes
ucl: 100 bytes compressed into 62 bytes
ucl: 100 bytes compressed into 57 bytes
ucl: 100 bytes compressed into 64 bytes
ucl: 100 bytes compressed into 59 bytes
ucl: 100 bytes compressed into 64 bytes
ucl: 100 bytes compressed into 72 bytes
ucl: 100 bytes compressed into 48 bytes
ucl: 100 bytes compressed into 50 bytes
ucl: 100 bytes compressed into 80 bytes
ucl: 100 bytes compressed into 66 bytes
ucl: 100 bytes compressed into 75 bytes
ucl: 100 bytes compressed into 67 bytes
ucl: 100 bytes compressed into 44 bytes
ucl: 100 bytes compressed into 65 bytes
ucl: 100 bytes compressed into 52 bytes
ucl: 100 bytes compressed into 77 bytes
ucl: 100 bytes compressed into 64 bytes
ucl: 100 bytes compressed into 53 bytes
ucl: 100 bytes compressed into 21 bytes
ucl: 100 bytes compressed into 64 bytes


Being 100 bytes a 20 x 10 tiles screen (using 4-bit per tile, that's 100 bytes).

That's 1472 bytes for the 25 screens, that's a 41.12% of savings (over 1K). And of course I use the uncompress code in other places, so it really pays off!

So exactly what @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) said!

Your 4-bit example is similar to what I used in Space Pest Control (and most recently in Castaway, a ZX Spectrum title). The CPCTelera functions must be really handy as they're highly optimised in ASM and I had to write mine for the same effect ;)

@EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) don't give up. Just give it time. What you're trying to achieve isn't simple, but you'll get it right eventually.
Title: Re: [cpctelera]Bit Arrays
Post by: FloppySoftware on 20:03, 26 February 16
Quote from: EgoTrip on 18:32, 26 February 16
This isnt the only reason I have given up. I keep encountering bugs that I can't fix and appear for no apparent reason, its stressing me out and im not having any fun doing this so whats the point.

To improve your programming skills can be a good reason to finish the project.  ;)

I have lots of unfinished projects, but they are not abandoned, just waiting for the right time.  ;)

BTW, nice bitmaps.  :)
Title: Re: [cpctelera]Bit Arrays
Post by: FloppySoftware on 20:07, 26 February 16
Quote from: SRS on 18:18, 26 February 16
;) - nice try. As others said  - if you need help, even coding that, we are here ! Maybe you can put it on GitHub for shared work.

It sounds nice! It seems a good opportunity for a team project.
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 20:56, 26 February 16
Quote from: EgoTrip on 18:32, 26 February 16
This isnt the only reason I have given up. I keep encountering bugs that I can't fix and appear for no apparent reason, its stressing me out and im not having any fun doing this so whats the point.
Well, I think most of us understand perfectly your feeling. This is normal when programming. Every programming project takes 1/3 of time for creative tasks and 2/3 for debugging and "have-to-do" tasks. That's the reason why it is so hard finishing projects and it is so valuable.

You've finished some projects already. That speaks well of you, specially if you had harsh moments like this one and continued till the end.

Your project looks very nice. I'd recommend you to take time to feel better and then decide on continuing or not. If you think it is going too complex, simplify it (remove features) and finish it. It is always better a smaller finished game than a greater unfinished one. Moreover, everything you learnt will let you face greater projects next time.

No matter what you decide, the most important thing is finding the way to enjoying it (even when it is difficult). Believe me if I say that you have plenty of reasons to be proud and enjoy what you are doing :) .
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 15:12, 27 February 16
Quote from: Arnaud on 18:30, 26 February 16
I tried an easy solution :

       
  • creation of a file with your data level.
  • use exomizer to compress in command line the data level : 160 -> 76 Bytes
  • convert with cpctelera the binary file into data.h
  • decompress the data level with the function cpc_UnExo from the cpcrslib
cpc_UnExo(dataLevelCompress, currentLevel);

That all !

Can you do a step by step guide showing me exactly what to do please? Including getting the cpcrslib and using it with a CPCtelera project? Thanks.
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 17:09, 27 February 16
Hello,
here a full project for cpctelera with your level in compressed file (level.bin) automatically converted in C file (level.c).

For information :
#include <cpctelera.h>
#include <cpcrslib.h>
#include <stdio.h>

extern const unsigned char G_level[76];
static unsigned char gCurrentLevel[160];

void main(void)
{
    int i, j, k = 0;
    cpc_UnExo(G_level, (int)gCurrentLevel);
   
    for (i = 0; i < 10; i++)
        for (j = 0; j < 16; j++)
        {
            if (j == 0)
                printf("\r\n");
            printf("%02X", gCurrentLevel[k++]);
        }

   while (1);
}


- To create the file of level data i used HxD (hexadecimal editor)
- To compress i used exomizer with the following commands line :
exomizer.exe raw level.dat -o t.out
exoopt.exe t.out level.bin

- And i moved level.bin directly in the src folder of cpctelera project

Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 18:59, 27 February 16
How/where do I install cpcsrlib?
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 19:59, 27 February 16
Quote from: EgoTrip on 18:59, 27 February 16
How/where do I install cpcsrlib?

you could download "level" (above), there it is included (*.h and *.lib). both files into your main path of game or compiler - then it should work
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 20:08, 27 February 16
@EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) if you are running out of memory, adding cpcrslib to your project is not a good idea. Depending on how you use it, it will add many bytes of code to your project. Taking into account that you are running out of memory, that's not the best solution.

It will be easier if you only add the function for unexomizing buffers. You only need to add a .s file with the assembly code of the function, and a header file to include with the declaration of the function. That will be faster and more efficient for your project.


EDIT: Attached you have a zip file the code for unexomizing. Uncompress it and put UnExoOpt.s in the src/ folder of your project. It will be automatically compiled. Then, when you wanted to use the function for uncompressing, you will need to declare the function with this line:
void cpc_UnExo(const u8* source, u8* dest) __z88dk_callee;
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 20:28, 27 February 16
@ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227) how do I find the ASM? I opened the files in the zip and there was the header file and another file with loads of bytes and some unreadable data.
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 20:36, 27 February 16
@EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) : I've just edited my last post and attached the file for you. In fact, I have reviewed the file and add a little patch to ensure it does not produce any kind of new bug.


I have not tested it, but it should work. If it gives any problem, report it here and we will have a look at it.


EDIT: Also, take into account that this code for exomizing takes 358 bytes of memory. I assume you will recover a lot more from compressing your data, but take this into account :).
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 10:33, 28 February 16
I have updated my project with asm in case you need working example.
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 10:55, 28 February 16
How do I convert the data RGAS outputs to a binary format exomiser can use?
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 11:36, 28 February 16
If you put your arrays in individual files, the compiler can do that for you. I'll show you an example.


1. Create a file examplemap.c which will only contain an imaginary map, and put it in src/ folder. (You could do this with any kind of data, be it maps, sprites or whatever).


#include <cpctelera.h>


const u8 an_example_map[] = {
   20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
   20,  0,  0,  0,  0,  0,  0,  0,  0, 20,
   20,  0,  3,  3,  3,  3,  3,  3,  0, 20,
   20,  0,  0,  0,  0,  0,  0,  0,  0, 20,
   20,  0,  2,  2,  0,  0,  2,  2,  0, 20,
   20,  0,  2,  2,  0,  0,  2,  2,  0, 20,
   20,  0,  2,  2,  0,  0,  2,  2,  0, 20,
   20,  0,  0,  0,  0,  0,  0,  0,  0, 20,
   20,  0,  0,  0,  1,  1,  0,  0,  0, 20, 
   20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
};



2. Compile the project. After compilation, a file obj/examplemap.rel is created, which contains this data, along with some information to link it to other files.


3. Enter obj/ folder and use sdcc to convert the REL file to an intel IHX binary:

   cd obj/
   sdcc examplemap.rel

This will create examplemap.ihx (also LK, MAP and MEM files, that are of no interest for us). If you open this file, you will see it is almost what we wanted.


4. Use hex2bin to convert de IHX file to a proper BIN file containing only our map data.

   hex2bin examplemap.ihx



With these simple commands, we have a perfect binary file containing exacly this:
[attachimg=1]


So, summing up, if you put your data in individual .c files, you can create binaries after compilation entering the obj/ folder and typing this:

   sdcc file2convert.rel && hex2bin file2convert.ihx

As simple as that, in the end.


PD: You will need to have sdcc and hex2bin in the PATH. If they are not in the path, you can insert them with this

export PATH=$PATH:${CPCT_PATH}/tools/hex2bin-2.0/bin/:${CPCT_PATH}/tools/sdcc-3.5.5/bin/

as both tools are included within CPCtelera (http://lronaldo.github.io/cpctelera) tools/ folder. (Depending on the release of CPCtelera (http://lronaldo.github.io/cpctelera) you are using, sdcc version might be a different one).
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 11:45, 28 February 16
To convert C to bin in manual way :

- From the C file i keep only the hexa values, with replace function of notepad  :

const unsigned char G_NewSprite1[36] = {
    0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB,
}


to

AA 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 BB


- i used hxd (simple hexadecimal editor) : mh-nexus (https://mh-nexus.de/en/)
- create new file
- copy / past from notepad text
- save

The binary file is created
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 12:33, 28 February 16
@Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) : having a manual way for doing things like this is always useful. In fact, it is interesting for everybody to start doing things manually to understand them better.

The automatic way is the way to go later on. For instance, if @EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) has around 20 maps, converting them on every modification he does could be painful. So, once command-driven conversion has been manually tested, a simple script would relief from pain:

#!/bin/bash

## Paths and files required for this script to work
FILES2CONVERT=( map1 map2 map3 finalmap )
SDCC=${CPCT_PATH}/tools/sdcc-3.5.5/bin/sdcc
HEX2BIN=${CPCT_PATH}/tools/hex2bin-2.0/bin/hex2bin
EXOMIZER=/path/to/exomizer

## Function that converts and exomizes 1 REL file
function convertAndExomize {
   $SDCC "${1}.rel"
   $HEX2BIN  "${1}.ihx"
   $EXOMIZER raw "${1}.bin" "${1}.exo"
}

## Enter obj/ folder and convert to binary and exomize all desired files one by one
cd obj/
for F in ${FILES2CONVERT[@]}; do
   convertAndExomize "$F"
done
cd -


With a script like this, you only have to run it along with your compilation line, and conversion gets automated.

   make && exomizeScript


You could even modify it to move the resulting files to the place where you wanted them to be.
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 12:35, 28 February 16
Theres no exoopt.exe in the exomizer zip. Can I just not use the data that the t.out file contains?
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 12:40, 28 February 16
@EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) : I think you got confused by the name of the asm file UnExoOpt.s. The "Opt" in that name stands for "Optimized" and refers to the assembly code, not to the exomizer format. The output exomizer gives you using "raw" modifier should be perfectly decompressed by cpc_UnExo function.
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 12:41, 28 February 16
Here the file, i don't remember from where i download it.
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 13:17, 28 February 16
Sorry, I was wrong with my previous comment. Didn't know of the exoopt (thanks, @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424)). I've been reading about it. As far as I've read, the latest version I've found of exoopt is from 28/01/2013 (attached). @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) , I think you should review your version, as it seems earlier to this one. Could you make a comparison of the outputs?
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 14:17, 28 February 16
I tried to use this version but now it needs parameters and i don't understand how use it (i think it's for asm generated)
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 14:54, 28 February 16
Its working! Thanks for all your help everyone.
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 13:46, 10 March 16
Quote
## Function that converts and exomizes 1 REL file
function convertAndExomize {
   $SDCC "${1}.rel"
   $HEX2BIN  "${1}.ihx"
   $EXOMIZER raw "${1}.bin" "${1}.exo"
}


is not working for me. I need to  $EXOMIZER raw "${1}.bin" -o "${1}.exo" else exomizer complains.

Question: if I put the "*.c" into SRC (lets say a 64 u8 "00"), the *.rel is way bigger (inlucdes crt0 at least ?) ->
so compressing the *.rel from "Make" really the right way ?

EXAMPLE ->

Raw Tile G_...c -> MAKE (CPCTeleraproject ...) -> putting *.REL to *.IHX to *.BIN and this back to C with
"cpct_bin2c G_Blank.bin > help.txt"

-> [attach=2]
Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 16:26, 10 March 16
Let's go with your problems one by one:
I think either you may have used an incorrect file at any given step, or my script does not work properly under some circumpstances I cannot see right now.
[attachimg=1]
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 20:20, 10 March 16
Quote from: ronaldo on 16:26, 10 March 16

       
  • Some part of this chain of steps is missing in your files. If I follow these steps manually starting with your G_Blank.rel, I get a totally different result (image attached). I have followed manually the 3 steps that are in the function: "sdcc G_Blank.rel; hex2bin G_Blank.ihx; exomizer raw G_Blank.bin -o G_Blank.exo".
I think either you may have used an incorrect file at any given step, or my script does not work properly under some circumpstances I cannot see right now.


Okay, lets try it manually:

***/cygdrive/e/cygwin64/home/Standardsurf/projekte/amy/obj
$ sdcc gblank.rel
-bash: sdcc: Kommando nicht gefunden.

Seems my cygwin PATH does not contain SDCC (but "Make" works, weired)  :picard: .


**********************

Try script, but only SDCC Pat, rest commented out:

#!/bin/bash

## Paths and files required for this script to work
FILES2CONVERT=( gblank GFRUIT1 GJEWEL1 GKEY1)
SDCC=${CPCT_PATH}/tools/sdcc-3.5.5/bin/sdcc
HEX2BIN=${CPCT_PATH}/tools/hex2bin-2.0/bin/hex2bin
EXOMIZER=${CPCT_PATH}/tools/exomizer/exomizer

## Function that converts and exomizes 1 REL file
function convertAndExomize {
   $SDCC "${1}.rel"
   ##$HEX2BIN  "${1}.ihx"
   ##$EXOMIZER raw "${1}.bin" -o "${1}.exo"
   ##cpct_bin2c "${1}.exo" > "${1}.txt"
}

## Enter obj/ folder and convert to binary and exomize all desired files one by one
cd obj/
for F in ${FILES2CONVERT[@]}; do
   convertAndExomize "$F"
done
cd -


Quote$ ./cruncher.sh

?ASlink-Warning-Undefined Global '_main' referenced by module 'crt0'

?ASlink-Warning-Undefined Global '_main' referenced by module 'crt0'

?ASlink-Warning-Undefined Global '_main' referenced by module 'crt0'

?ASlink-Warning-Undefined Global '_main' referenced by module 'crt0'
/home/Standardsurf/projekte/amy


the IHX generated now
:03000000C3000139
:02000800ED4DBC
:02001000ED4DB4
:02001800ED4DAC
:02002000ED4DA4
:02002800ED4D9C
:02003000ED4D94
:02003800ED4D8C
:0C010000310000CD4A02CD0000C3040213
:0A0200003E02CFC93E00CF7618FD84
:10024A0001000078B12808110080214A02EDB0C9E6
:20020A000000007000000070000000A0000010200000204010E04040211CF080433B874062
:20022A00873A0EEC872D0EDC872D0F12872D0F1E432D0F1E211E0F2C10E0874800007080DF
:00000001FF



scripted hex2bin only give :

Quotehex2bin v2.0, Copyright (C) 2015 Jacques Pelletier & contributors

Binary file start = 00000000
Records start     = 00000000
Highest address   = 00000259
Pad Byte          = FF
hex2bin v2.0, Copyright (C) 2015 Jacques Pelletier & contributors

This is to big. No wonder, the generated bin shows ->[attach=2]

So it seems compiling / linking it always with some crt0


Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 20:58, 10 March 16
Okay, brand new project, no main, compiling the C alone - still it seems it does not make "plain code"

see screener and zip.

The "knackpunkt" seems the way my sdcc compiles this C. it is not plain ...


Title: Re: [cpctelera]Bit Arrays
Post by: ronaldo on 21:41, 10 March 16
Ok, @SRS (http://www.cpcwiki.eu/forum/index.php?action=profile;u=805) , you are plainly right. This was my mistake from the start.

The problem is that SDCC 3.5.0 has different behaviour to SDCC 3.5.5 (which is the one included in latest CPCtelera (http://lronaldo.github.io/cpctelera)). I have SDCC 3.5.0 in my $PATH, so it was working for me, but it won't work for you as you are using SDCC 3.5.5.

With SDCC 3.5.5 you have to do this change:

-#   $SDCC "${1}.rel"
+#   $SDCC "${1}.rel" --no-std-crt0

You were correct, SDCC is including aditional bytes from the standard CRT0.

Sorry for not spotting this one earlier on and thank you for all your detailed tests and contribution :)
Title: Re: [cpctelera]Bit Arrays
Post by: SRS on 22:08, 10 March 16
@ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227), thx for your patience and quick responses.

>joke mode on<
You better "make cleanall make" all your examples for CPCtelera if it still works with your new PATH/SDCC ?  ;D
<joke mode off>

Now it works!

Inbetween I tried @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) method. Works like charm once you know how to use the hex editor !

Sadly the tiles i wanted to compress get out bigger after exomizing then in "raw", so no use for @EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) game here. But for sure in future games.


For all that need the full skript: (windows user don't forget to save it in UNIX-mode (LF only, no CR + LF), else cygwin will not run it ...)

You need latest CPCTelera and have to download/copy "exomizer.exe" to the tool path of CPCTelera (see below), too !

#!/bin/bash

## Paths and files (ttlmus is just an example) required for this script to work
FILES2CONVERT=( ttlmus )
SDCC=${CPCT_PATH}/tools/sdcc-3.5.5/bin/sdcc
HEX2BIN=${CPCT_PATH}/tools/hex2bin-2.0/bin/hex2bin
EXOMIZER=${CPCT_PATH}/tools/exomizer/exomizer

## Function that converts and exomizes 1 REL file
function convertAndExomize {
   $SDCC "${1}.rel" --no-std-crt0
   $HEX2BIN  "${1}.ihx"
   $EXOMIZER raw "${1}.bin" -o "${1}.exo"
   cpct_bin2c "${1}.exo" > "${1}.txt"
}

## Enter obj/ folder and convert to binary and exomize all desired files one by one
cd obj/
for F in ${FILES2CONVERT[@]}; do
   convertAndExomize "$F"
done
cd -
Title: Re: [cpctelera]Bit Arrays
Post by: SpDizzy on 10:47, 14 July 18
First of all, sorry for reopen this thread after so much time guys  :picard:

I was testing with the code from @SRS (http://www.cpcwiki.eu/forum/index.php?action=profile;u=805) and profe @ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227) to compress and exomize a .rel file from /obj folder after project compilation with 'make' command.

Everything works perfectly, and a .txt file is obtained with level data.

So here are the questions...

1/ ¿Where to go form here? I mean, how to convert this 'level.txt' into 'level.c' and 'level.h' and unexomize data on the fly?

2/ I understand is necessary after level compression and exomization, to re compile project with new compressed 'level.c' and 'level.h' something like > 'make clean' > 'make cleanall' > 'make', am I correct?

3/ Does @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) approach work the same way? It seems to require a 'level.bin' file, automatically converted in 'level.c' and 'level.h' after compilation.

Once again sorry for the delayed comment, please feel free to delete it if it's not appropiate.
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 19:05, 15 July 18
Quote from: SpDizzy on 10:47, 14 July 18
1/ ¿Where to go form here? I mean, how to convert this 'level.txt' into 'level.c' and 'level.h' and unexomize data on the fly?
Exactly, rename level.txt into level.h. include it into your code and deflate the array of compressed data to free memory area

Quote from: SpDizzy on 10:47, 14 July 182/ I understand is necessary after level compression and exomization, to re compile project with new compressed 'level.c' and 'level.h' something like > 'make clean' > 'make cleanall' > 'make', am I correct?
Yes, because new source files are generated and need to be compiled to make an executable

Quote from: SpDizzy on 10:47, 14 July 183/ Does @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) approach work the same way? It seems to require a 'level.bin' file, automatically converted in 'level.c' and 'level.h' after compilation.
Yes this the same way, the automatic convertion of cpctelera bin to c is used, that all.

Quote from: SpDizzy on 10:47, 14 July 18Once again sorry for the delayed comment, please feel free to delete it if it's not appropiate.
No worry of that  ;D
And a new cpcretrodev contest is a good time to code.
Title: Re: [cpctelera]Bit Arrays
Post by: SpDizzy on 17:03, 16 July 18
Thanks so much for your quick response and amazing support @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) , it works like a charm!!
All clear now for me, it's a complete joy to have all the questions solved in no time by authentic professionals.
Making an amstrad videogame was allways my dream since my first micro (cpc 464) arrived on home 30 years ago, but I think I need to improve my coding skills a bit more to get it.
Obviously @ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227) has the key for success on cpcretrodev contest: "Programad insensatos!"  ;D
Title: Re: [cpctelera]Bit Arrays
Post by: Arnaud on 17:56, 16 July 18
Quote from: SpDizzy on 17:03, 16 July 18
Thanks so much for your quick response and amazing support @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) , it works like a charm!!
All clear now for me, it's a complete joy to have all the questions solved in no time by authentic professionals.
Making an amstrad videogame was allways my dream since my first micro (cpc 464) arrived on home 30 years ago, but I think I need to improve my coding skills a bit more to get it.
Obviously @ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227) has the key for success on cpcretrodev contest: "Programad insensatos!"  ;D
Thanks  ;)
You should try to make an "easy" (nothing is really easy with coding) game, you'll find all support needed here with forum members.
Title: Re: [cpctelera]Bit Arrays
Post by: EgoTrip on 12:00, 18 July 18
Quote from: SpDizzy on 17:03, 16 July 18
Thanks so much for your quick response and amazing support @Arnaud (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1424) , it works like a charm!!
All clear now for me, it's a complete joy to have all the questions solved in no time by authentic professionals.
Making an amstrad videogame was allways my dream since my first micro (cpc 464) arrived on home 30 years ago, but I think I need to improve my coding skills a bit more to get it.
Obviously @ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227) has the key for success on cpcretrodev contest: "Programad insensatos!"  ;D
If you are converting a lot of things, I shared my batch file to make it a lot easier.
http://www.cpcwiki.eu/forum/programming/exomizer-batch-script/msg132692/#msg132692
Title: Re: [cpctelera]Bit Arrays
Post by: SpDizzy on 10:31, 21 July 18
Quote from: EgoTrip on 12:00, 18 July 18
If you are converting a lot of things, I shared my batch file to make it a lot easier.
http://www.cpcwiki.eu/forum/programming/exomizer-batch-script/msg132692/#msg132692 (http://www.cpcwiki.eu/forum/programming/exomizer-batch-script/msg132692/#msg132692)
Oh, thanks so much @EgoTrip (http://www.cpcwiki.eu/forum/index.php?action=profile;u=337) , I hope you could finish your project  ;)
Powered by SMFPacks Menu Editor Mod