EVN Editor (NovaGod)

Quote

Originally posted by AriosSw:
**Hehe, EVONE was started on January 28 of this year, and is just now becoming fully operational. That is the difference between Carbon and Cocoa.

**

Yep, rapid application development without language limitations : )

The app would have taken a fair bit longer but I'm making a Cocoa document based application, so not only is all of the default behaviour taken care of (as in Carbon) but also all the menu/control handling between documents is also taken care of.

The Outlet/Action thingamajig in Cocoa also makes it much easier to manipulate controls, and of course, in Cocoa you don't have to fiddle with Lists as much as in Carbon.

But, lovely things such as the interface haven't really been the focus lately, I'm writing data management code for the common resources (EVN Data 1, etc). In fact, I haven't even bothered to put icons on the buttons of the main plugin window! (I'm relying on Tooltip messages to remind me which button does what!)

Cheers!

------------------
Kane O'Donnell

Quote

Originally posted by shado83:
I've been out of the REALBasic game too long - I've never heard of an RGBSurface...or maybe I've just forgotten...

It's a faster way of editing an off-screen graphic pixel by pixel.

Quote

04: The remaining 24 bits is the number of pixels you should fill with colour described by the NEXT FOUR BYTES. So, on an 8 bit system, 04000010 000000FF would mean fill the next 16 pixels with the colour at index 255 in the colour palette used by the RLE. For the default palette this is black.

I actually downloaded SpriteWorld and patched together a fairly workable RLE decoder based on its documentation the other day, but this token is the only one I couldn't get to work properly. How exactly is the fill colour specified here? Reading it as a colour value the way I did with the draw pixels token didn't seem to work.

Quote

The trick (and this is important!) is keeping your memory pointer aligned so that when it reads a LONG (4 bytes) it always reads, say 01000000 instead of 00000100. This is because whilst the tokens are 4 bytes, the pixels are either 1 or 2 bytes, and so the pointer can get misaligned during the draw and single colour draw operations.

I'm not quite sure what you're getting at here - are you just saying to count the pointer by bytes rather than by tokens?

------------------
David Arthur @ (url="http://"http://davidarthur.evula.net/")davidarthur.evula.net(/url)
(url="http://"http://www.ev-nova.net/faq/")EV Nova Gameplay FAQ(/url) - Now Hosted by (url="http://"http://www.ev-nova.net/")EV-Nova.net(/url)!

Quote

02: The remaining 24 bits tell you that the next N bytes are pixel data, so the token 02000004 (in hex) would be followed by 4 bytes (8 hex characters) of pixel data. Of course, whether 1 byte = 1 pixel or 2 bytes = 1 pixel depends on whether you're using 8 or 16 bit rle's, but the same algorithm can be used for both with no modifications (lucky, hey!).

So what exactly is in this pixel data? Would it include the color of the pixel, or just saying that a pixel is there?

Quote

04: The remaining 24 bits is the number of pixels you should fill with colour described by the NEXT FOUR BYTES. So, on an 8 bit system, 04000010 000000FF would mean fill the next 16 pixels with the colour at index 255 in the colour palette used by the RLE. For the default palette this is black.

So in an 8 bit sytem, the FF stands for the color on the pallete, from index 0-255. Is there any chart for the colors on every pallete, or is there some way to seperate it into rgb values? Also for a 16 bit system, would we use a 32567 (or whatever) sized pallete, or is there a rgb system?

Quote

I'm not quite sure what you're getting at here - are you just saying to count the pointer by bytes rather than by tokens?

I'm also slightly confused by this, should we load it byte by byte(two hex chars), or token by token (four)?

Unfortunately, I haven't done too much work with memory OR rgb surfaces, so I am doing this all theoretically until I have a chance to figure out how to do it in RB. Thanks for all of the help, by the way.

------------------
Eat blazing electric death!
(url="http://"http://www.geocities.com/infernomsh")Inferno Studios)(/url)
(being remade better than ever!)

Quote

Originally posted by David Arthur:
**I actually downloaded SpriteWorld and patched together a fairly workable RLE decoder based on its documentation the other day, but this token is the only one I couldn't get to work properly. How exactly is the fill colour specified here? Reading it as a colour value the way I did with the draw pixels token didn't seem to work.
**

I believe it is refering to a color palette and not a color value. in 16 bit color I'm not shure this would seem to be the right way to go about doing that but It doesn't appear to be otherwise.

I am also having trouble with the color as I can't seem to find the palette, either 8 or 16 bit.

------------------
(url="http://"http://snow.prohosting.com/thorprim/")NovaBurst Home(/url)

This is why I said to use a MemoryBlock first. 🙂 What follows is really long and a bit technical.

In RB you don't have pointers to memory. The BASIC language description only has Rvalue data types, as far as I can remember. So think of a pointer as a signpost to a memory location. The only equivalent you have is the pointer of the MemoryBlock class.

Firstly - pixel data is just the colour. Location is NOT taken care of by pixel data - this is why pointer management is so important, because otherwise you'll put the wrong colour in the wrong place.

An 8 bit indexed RGB system uses 8 bits (= 1 Byte = 2 Hex characters = range from 0-255) to 'index' a colour from a colour chart. The colour chart to use is that specified in the PALETTE field of the RLE resource. If zero is in this field, you use the STANDARD SYSTEM PALETTE for 8 bit (256 colours) RGB. The point to remember is that you're not getting a direct colour value from the RLE data, you're getting an index number to a colour chart. In 8 bit, an index can be at most 1 byte in size, hence 8 bit colour. 16 bit colour contains an index to a 32768 colour chart, 32 bit to around 19 million colours and so on. The RLE data is an INDEX.

So, with that in mind, you can change what the index numbers mean by putting a non zero number in the PALETTE field of the RLE resource and creating a 'clut' resource that contains the colours you want to use. But, it would be better not to stuff around with this, I think, unless you're creating something like a Borg Cube and only need a wide selection of greens and greys, and no other colours.

By the way, I'm Aussie, I spell colour as colour.

Back to the 04 token. Say you have the data 0100000C 0300000A 04000010 0000 00FF 010000AF....

The pointer initially starts at the beginning, before the first token. You read a long integer (4 bytes) and you have 0100000C, remember 1 byte = 2 hex chars. This token means begin a new line, and the C means that there are 12 bytes (BYTES!!) before the next line. That is, there is twelve bytes of data (not including the 4 you've already read) for this line of the shape.

Because this was a new line token, you don't need to worry about following data, so you advance the pointer 4 bytes to the beginning of the next token. In RB THIS IS DONE FOR YOU! Yay. In C, it isn't. Boo. Use data += sizeof(long) or data += 4, the first is preferable. Also, you have to advance your PIXEL pointer by the length of a line - like I said before, the RLE contains no info about the locations of individual pixels, you just have to iterate through your pixel map. SO say your RLE is 24 pixels wide and each pixel is 1 byte (in 8 bit), you have to advance your pixel pointer 24 bytes. Actually, in C it isn't that simple, but that's a different topic. In RB, advance your MemoryBlock pointer by 24 characters for 8 bit (1 char = 1 byte).

The next token is 0300000A. This is also a simple one. The 03 means skip, and the A stands for decimal 10, so you skip the next 10 pixels. Once again, advance your pixel pointer 10 pixels. Also, advance your data pointer by sizeof(long) again.

The next token is 04000010. This is where the fun starts. The 04 means there is a 'run' of pixels that are all the same colour, and to save space they have been run length encoded. Run Length Encoded. RLE. Hmm? The other 24 bits, the 000010 means that the NEXT 16 PIXELS ARE ALL THE SAME COLOUR. But what colour? Well, wait a minute. Advance your data pointer by 4 bytes again, because you're done with the token. Once again, RB does this automatically when you call MemoryBlockObject.ReadLong(). Now, to find out the right colour, READ THE NEXT FOUR BYTES. That is, read another long. Now even though this number is a 'long' data type, it must be between 0-255 inclusive for 8 bit, and 0-32767 for 16 bit. If it isn't, Quickdraw will reduce it anyway, so say you have 256 (00000100 in Hex), this will wrap to the colour indexed zero in 8 bit colour. In any case it SHOULD be 0-255 in our example, and it is, because FF = 255 = BLACK in the standard 8 bit colour chart. So the NEXT 16 PIXELS are ALL BLACK, you just have to cycle through the next 16 pixels and fill them with black. It's as simple as that. Don't forget to advance your data pointer by a long again (automatic in RB). The last token I put up there was the next new line token. Notice it starts 12 bytes after the last new line token, just as we expected.

So, you need two things to decode. Don't even think about graphics yet. Think data. You have one MemoryBlock filled with the RLE data. You have one MemoryBlock that has enough space to hold the pixel data for each pixel in the RLE. So, for the shuttle (108 frames, I think, and 24 pixels high/wide) in 8 bit colour, you need 12424108 bytes of data. For the 16 bit RLE you need 22424108 bytes.

Then, you go through and decode from the first block to the second. Don't forget that the RLE data has a HEADER - 16 bytes. You need to read the header data first! Then, the tokens start right after the last Reserved short.

The SECOND block is now your pixel data. In 8 bit, each byte is an index for a pixel. There will be 24 pixels to a line, and 24 lines to a shape. Figuring out what pixel goes where is totally your job - the pixel data is RAW. It's just a bunch of colour indexes. Remember for 16 bit, each SHORT will correspond to one pixel, because in 16 bit, you have 2 bytes for each pixel.

Finally, what did I mean by keeping your pointer aligned? Well in RB you still have to worry about this, and it only arises when you're using the 02 token. I'll describe it in the next post because this one is getting really long.

Read on!

------------------
Kane O'Donnell

Okay, let's talk about the 02 token. As you know, this is of the format 02XXXXXX, where the XXXXXX is a number that describes how many BYTES of data follow.

Now hang on, because at the moment I don't have access to a resource fork (cringe) and I can't remember off the top of my head whether the XXXXXX means the number of bytes or the number of pixels. In any case for 8 bit it's the same, so I'l just assume we're in 8 bit for the following example. I'll follow up this post tomorrow when I have access to a resource fork (I'm using my girlfriend's PC at the moment).

So, on to the example. We have the data:
01000014 0300000A 02000009 FFAAFFAA FFAAFFAA FF000000 010000AA......

Once again the first token is a new line long, the 14 means that there are 20 (14 = 16+4 = 20) bytes of data to follow for this line.

Advance your pointer by 4 bytes if you're in C.

The next token, 0300000A, just means skip the next 10 pixels. Read the last post for details. Advance your pointer by 4 bytes if in C, and advance your pixel pointer by 10 pixels (10 bytes in 8 bit colour). You have to do the pixel advance EVEN IN RB. There are serious (read=ultra, ultra serious, probably fatal) problems with using RB to stuff around with RLE's. When you try and encode one, you'll understand why. Decoding, however, is no problem. If you don't want to encode, you can skip the next para.

What is the encoding problem? Well, the beauty of RLE data is that it allows you to simply SKIP pixels - your shape doesn't need to be rectangular. This means you can have total transparency where you need it, without a mask. That's where the mask went! But to encode an RLE, you need a mask, because you need to know which pixels to skip. The easiest way to do this is to fill all the parts of an RLE that you DON'T want with a single colour, a MASKING COLOUR. It usually can't be black because most RLE shapes will have some black in them. Pick a wierd colour. Now, in RB, you MUST FILL your pixel MemoryBlock with this colour BEFORE you start decoding the RLE. Every byte. You see why? Because when you finish decoding, the MemoryBlock will STILL HAVE the masking colour in all the places you skipped, and encoding is no problem - you just have to skip all the masked pixels. If you don't do the mask first, you will be in trouble - when you go to encode, you won't know which pixels are masked!! So if the mask colour is indexed as 1A, your MemoryBlock data would look like 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A.... before you started decoding, and afterwards it might look like 1A1A1AFFFF1AFF1A1AFFFFFF1A. The mask remains. Good stuff. Moving on...

Just so you don't have to scroll back up, the rest of the data in our example is 02000009 FFAAFFAA FFAAFFAA FF000000 010000AA.

The first token of this data is 02000009, and here the fun starts again. This token means that the next 9 pixels (or bytes, I'll clarify in another post, but for now 1 pixel = 1 byte so it doesn't matter) are to be filled with the pixel data that follows.

How do you deal with this? Well first advance your data pointer by a long, if in C. Now you're reading bytes, not longs. Read a byte. Copy this value to the pixel MemoryBlock. Advance the data pointer one byte, and ALSO advance the pixel pointer one byte. Read a byte. Copy this value to the pixel MemoryBlock... and so on. Remember to advance the pixel pointer by one byte each time as well as the data pointer. You do this 9 times. Why? Because the 02000009 token said to.

Now, what do we do? We might mistakenly think, 'right, time for the next token!' and read a long. What do we get if we do that? 00000001. Is that a token? YES - it's an end of shape token, and if you made that mistake the image would have ended right there. For some reason the Shuttle rle8 resource can't be stuffed up like this, so I never picked up this mistake until I loaded the Enterprise shape, which was clipped to only 20 lines, and something was obviously wrong.

The mistake was that tokens ONLY start on long-even offsets. What this means is that if you look above at the example data, I've grouped it in sets of 8 hex characters = 4 bytes. This is how you MUST read the data. This is what I mean by keeping the data pointer aligned. Because 9 (bytes) isn't a multiple of 4, the data pointer ISN'T IN LINE WITH THE TOKEN! Therefore, you have serious problem. To fix it, you NEED a pointer alignment routine. In BlitPixie there is a lovely little macro that does this in C, but it doesn't work in ProjectBuilder properly. The simple pseudocode for my alignment routine is:

Find the remainder of the division N/4, where N is the number of bytes you just advanced.

If remainder = 0, don't worry.
If remainder = 1, advance the DATA pointer 3 more bytes.
If remainder = 2, advance the DATA pointer 2 more bytes.
If remainder = 3, advance the DATA pointer 1 more byte.

This can be written much more efficiently in C. Note that this has nothing to do with the pixel pointer. SO, now the data pointer is aligned, and you can read the last token, which is just a new line token.

So that's what I'm talking about when I go on about pointer alignment. Tokens only occur on long-even intervals. It's a problem even in RB, so deal with it when it occurs - every time the 02 token appears.

Like I said at the beginning, the NNNNNN in 02NNNNNN might be the number of pixels, in which case the number of bytes is NNNNNN*2 for 16 bit, or it could be the number of bytes. I'm fairly sure it's bytes, not pixels, but I'll check. I can't remember off the top of my head. In 8 bit, none of that matters. It only matters in 16 bits.

My advice is just to use 8 bit until you're comfortable because the 1-1 correspondence between bytes and pixels makes life easy.

Enjoy coding!

------------------
Kane O'Donnell

Quote

Originally posted by shado83:
**
<jargon>
**

hrm...I thinks I will stick with plug-ins.

I must commend you on your quick work. As a suggestion/request, I would like to see some sort of visual way to edit s˙sts. Something like EV Developers Map.

------------------
"Moronic User Error. Details:If I had hands I would slap you silly."
"It must be a common fault. I see that error message all the time."-(url="http://"http://freefall.purrsia.com/")Freefall(/url)
"I told you never to speak of that again!"
"...and I chose to ignore you."-(url="http://"http://www.peterandcompany.com")P&C;(/url)

Quote

Originally posted by shado83:
An 8 bit indexed RGB system uses 8 bits (= 1 Byte = 2 Hex characters = range from 0-255) to 'index' a colour from a colour chart. The colour chart to use is that specified in the PALETTE field of the RLE resource. If zero is in this field, you use the STANDARD SYSTEM PALETTE for 8 bit (256 colours) RGB. The point to remember is that you're not getting a direct colour value from the RLE data, you're getting an index number to a colour chart. In 8 bit, an index can be at most 1 byte in size, hence 8 bit colour. 16 bit colour contains an index to a 32768 colour chart, 32 bit to around 19 million colours and so on. The RLE data is an INDEX.

Even in the DrawPixels token? There, I seem to be able to decode it as an RGB value when I'm dealing with 16-bit RLEs.

Quote

The next token is 04000010. This is where the fun starts. The 04 means there is a 'run' of pixels that are all the same colour, and to save space they have been run length encoded. Run Length Encoded. RLE. Hmm? The other 24 bits, the 000010 means that the NEXT 16 PIXELS ARE ALL THE SAME COLOUR. But what colour? Well, wait a minute. Advance your data pointer by 4 bytes again, because you're done with the token. Once again, RB does this automatically when you call MemoryBlockObject.ReadLong(). Now, to find out the right colour, READ THE NEXT FOUR BYTES. That is, read another long. Now even though this number is a 'long' data type, it must be between 0-255 inclusive for 8 bit, and 0-32767 for 16 bit. If it isn't, Quickdraw will reduce it anyway, so say you have 256 (00000100 in Hex), this will wrap to the colour indexed zero in 8 bit colour. In any case it SHOULD be 0-255 in our example, and it is, because FF = 255 = BLACK in the standard 8 bit colour chart. So the NEXT 16 PIXELS are ALL BLACK, you just have to cycle through the next 16 pixels and fill them with black. It's as simple as that.

So here I have to look up a colour index?

Anyway, I've got a decoder that seems to work for most 16-bit RLEs, even multi-frame ones, except for two things:

  • I don't have a working decoder for the SingleColor token yet, because of the indexed colour thing, but very few resources seem to actually use this token. For the same reason, I don't have an 8-bit RLE decoder yet either.

  • On a few RLEs - mostly ones with large pixel dimensions - I'm still finding unexpected LineStart and EndShape tokens. I've checked the pointer tracking, and it seems to be working all right - I am rounding up to the nearest multiple of four bytes when getting the extra data for the DrawPixels token - so I'm not sure why this is happening.

For my purposes, I probably won't need an encoder, and I can probably do without an 8-bit decoder, although it would be nice to have one for the sake of completeness.

------------------
David Arthur @ (url="http://"http://davidarthur.evula.net/")davidarthur.evula.net(/url)
(url="http://"http://www.ev-nova.net/faq/")EV Nova Gameplay FAQ(/url) - Now Hosted by (url="http://"http://www.ev-nova.net/")EV-Nova.net(/url)!

Quote

Originally posted by Admiral Benden:
**As a suggestion/request, I would like to see some sort of visual way to edit s˙sts. Something like EV Developers Map.

**

(url="http://"http://www.ariossoftware.com/pub/galaxy/")http://www.ariossoft...com/pub/galaxy/(/url)

These pictures are a little outdated, but the interface has only gotten more beautiful and easier to use, so this should give you a relatively good idea of what it can do.

If you also want to see a graphical view of a single system, allowing you to position spobs etc, try:
(url="http://"http://www.ariossoftware.com/pub/syst/")http://www.ariossoftware.com/pub/syst/(/url)

EVONE can do both of these things right now and so much more. A public beta of EVONE is expected to be released somewhat soon (within a month), as soon as I fix some stupid bugs in the registration system.

Jeffrey - Arios SoftWare

------------------
(url="http://"http://www.ariossoftware.com/upcoming")EVONE 1.0.0 - the plugin editor for EV/EVO/EVN(/url)

Quote

Originally posted by David Arthur:
**So here I have to look up a colour index?

Anyway, I've got a decoder that seems to work for most 16-bit RLEs, even multi-frame ones, except for two things:

  • I don't have a working decoder for the SingleColor token yet, because of the indexed colour thing, but very few resources seem to actually use this token. For the same reason, I don't have an 8-bit RLE decoder yet either.

  • On a few RLEs - mostly ones with large pixel dimensions - I'm still finding unexpected LineStart and EndShape tokens. I've checked the pointer tracking, and it seems to be working all right - I am rounding up to the nearest multiple of four bytes when getting the extra data for the DrawPixels token - so I'm not sure why this is happening.

For my purposes, I probably won't need an encoder, and I can probably do without an 8-bit decoder, although it would be nice to have one for the sake of completeness.

**

You might want to still have an 8 bit decoder because plugin developers may want to see how their 8 bit version looks : )

The single colour token isn't in any resources that I have seen, and it was inserted into SpriteWorld after the original BlitPixieRLE procedure was made (look at the source code). If it doesn't bother you, don't bother it : )

Unexpected linestarts/end shapes can pretty much only be a misaligned pointer. Remeber in 16 bits you have to advance in bytes still, not in 2*bytes, for the pointer alignment, so you still do N/4:

If N/4 has remainder of:
0 - advance 0 bytes
1 - advance 3 bytes
2 - advance 2 bytes
3 - advance 1 byte.

If you're still having trouble, you can send me a text version of your source if you like, I'll see if I can help. I don't think I have the latest version of RB (I've only got 2.0) so it would have to be text.

Cheers!

------------------
Kane O'Donnell

Quote

Originally posted by shado83:
You might want to still have an 8 bit decoder because plugin developers may want to see how their 8 bit version looks : )

Yes, I probably will - it's just a matter of getting the lookup tables set up properly.

Quote

Originally posted by shado83:
**Unexpected linestarts/end shapes can pretty much only be a misaligned pointer. Remeber in 16 bits you have to advance in bytes still, not in 2*bytes, for the pointer alignment, so you still do N/4:

If N/4 has remainder of:
0 - advance 0 bytes
1 - advance 3 bytes
2 - advance 2 bytes
3 - advance 1 byte.**

This is how I'm handling the dummy characters at the end of a DrawPixelsToken:

indx = indx+(Ceil(count/4)*4)

What I'm doing is handling both the advancing past the data and the dummy values using the same line of code; it does the same thing as the remainder trick, only with a bit less code. This divides the 'count' value (the number of bytes) by four, rounds up to the nearest whole number, and then multiplies by four again. I'm also checking at the beginning of every loop that the indx variable (my data cursor) is a multiple of four, and rounds up to the nearest one if it isn't.

The unexpected linestarts and endshapes only seem to occur in resources which use the singlecolor token, which makes me suspicious about it. The pointer should be advanced a further four bytes after reading it, correct?

------------------
David Arthur @ (url="http://"http://davidarthur.evula.net/")davidarthur.evula.net(/url)
(url="http://"http://www.ev-nova.net/faq/")EV Nova Gameplay FAQ(/url) - Now Hosted by (url="http://"http://www.ev-nova.net/")EV-Nova.net(/url)!

Quote

Originally posted by AriosSw:
**< snip>
**

That's all well and good for EVONE, but I am making this a request for NovaLord. I don't want to participate in the Beta, as using software that has the potential to bugger my plug-ins is not highest on my priority list. Plus the fact that it is shareware, and though ten dollars may not seem like much, it is when you have other expenses and are on a limited budget.

------------------
"Moronic User Error. Details:If I had hands I would slap you silly."
"It must be a common fault. I see that error message all the time."-(url="http://"http://freefall.purrsia.com/")Freefall(/url)
"I told you never to speak of that again!"
"...and I chose to ignore you."-(url="http://"http://www.peterandcompany.com")P&C;(/url)

Don't worry, Admiral. We are trying to kill as many bugs as possible, and even right now there are few or no fatal flaws in EVONE.

Thanks for those clarifications, shado. Unfortunately I'm still way behind on my coding, but I now understand how it should work in theory. I never realized that the skip was actually from the mask, and it makes a lot of sense now. I should start making my decoder whenever I get some free time.

------------------
Eat blazing electric death!

Quote

**

The unexpected linestarts and endshapes only seem to occur in resources which use the singlecolor token, which makes me suspicious about it. The pointer should be advanced a further four bytes after reading it, correct?

**

Yes, the data pointer should be advanced 4 bytes, and obviously you have to move the pixel pointer (if you're using one) forward the number of pixels you just copied to.

The pointer alignment code you put up certainly does the right thing. You don't need to align the pointer after a single colour op.

We'll have to carry this conversation on by private email or this topic will be moved somewhere else : )

Cheers!

------------------
Kane O'Donnell

Some general updates:

1. The application shell is about 75% complete. I'm expecting to have most of the remaining finished tomorrow and after that I will be fine tuning. I think a working application (no editors, no frills) will be finished by the end of Friday.

2. David Arthur & co - I was watching the shuttle spin round and round and I realised that the number of pixels in a row (24) didn't match the number of bytes to the row (32) even in 8 bit. In fact, when I changed the code to force the length of the line to 24 pixels, I got unexpected line starts and end of shape tokens...I think this may have some bearing on your problem. I'm not quite sure why, but each row takes more bytes than pixels. I can't determine a formula for the increase yet. I've been using a function in the QuickDraw API called GetPixRowBytes to get the exact number, and when I use it I get no problems. You might have to lookup the QuickDraw API documentation on the Apple website (Carbon docs) and look up the PixMap data type - it might explain what's going on. The same happens in 16 bit but the increase is bigger - the row size for the shuttle is 64 bytes, a 40 byte increase.

Cheers!

------------------
Kane O'Donnell