|
-
Jul 14th, 2012, 11:44 PM
#1
Thread Starter
Frenzied Member
The Best GGD That Was Ever Made
That is actually the title of this program I wrote (using VB6). It is based on the a sprite dumping software called GGD, which stands for Game Graphics Dumper. GGD was basically a very fancy version of a RAW image loader. It can take ANY file, and it does not know the format, nor how to read any header, so you supply a LOT of info so GGD can load the Graphics (stuff like, offset to image data, height, width, tiled or linear arranged pixels, color channel order, bits per pixel, offset to palette data, and all the same formats for the image are repeated for the palette, selectable endianness, etc). This way almost ANY format you can imagine (as long as it is in RGB or RGBA colorspace, cause YUV doesn't work here) that might ever be found in any video game or any other source (and as long as it isn't encrypted or compressed), can be displayed and saved as an ordinary bitmap file.
Well the controls for the original GGD were not user friendly, and the documentation was in Chinese or Japanese, so it was basically a "if you only know English, figure it out for yourself" type software (although some hacker made a translated version in English later, the controls still were horrible). Then came one called Tiled GGD that had some extra options for tiled graphics, including options for planar arranged color channels (instead of per-pixel arranged color channels, though I think planar color channels were also available in the original GGD), and it was based on GGD (it was a derivative work you might say), but it was made by an English speaking guy (luckily), and the controls were easier to use. However it lacked a number of features of the original GGD, namely it lacked the ability to arange the bit masks that were used to define which bits in a 16 (or 15) bit per pixel image were used for what colors, and also what ones were used for alpha (if any at all).
Well my program called "The Best GGD That Was Ever Made" is my own take on how the GGD program should have been designed, and has the functionality missing from Tiled GGD, which existed in the original GGD. It also is designed to have a much more intuitive user interface than the original GGD. To load a file, just drag it Windows explorer onto most any spot in the GUI, then press "load file" button. If it doesn't look right, change some of the parameters and press "load file" again. To load a palette, drag a file that you believe has the color palette for the image into the square black box and check the box "Use External palette", then press the "load file" button again. If the palette looks wrong, adjust the palette parameters and press "load file" again. To save a palette, select the option button (radio button) for the palette format you want, and press "save palette". When the picture looks right, press the "save image" button to save the image as a BMP file.
Below here is the VB code for the software.
Click to view: http://pastebin.com/raw.php?i=3tSjajtx
Click to download TXT file: http://pastebin.com/download.php?i=3tSjajtx
Here's the code that sets up the form in the FRM file.
Click to view: http://pastebin.com/raw.php?i=fLp30wPe
Click to download TXT file: http://pastebin.com/download.php?i=fLp30wPe
Here is a screenshot of the GUI:

It also has one dependency that isn't a normal VB6 runtime file. Download the DLL file at: http://www.dllbank.com/zip/n/nctimagefile.dll.zip
Last edited by Ben321; Jul 14th, 2012 at 11:49 PM.
-
Jul 15th, 2012, 10:43 AM
#2
Re: The Best GGD That Was Ever Made
Excellent work! 
BTW, was the original GGD coded in VB Classic? Or, did you have to port it?
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jul 15th, 2012, 07:10 PM
#3
Thread Starter
Frenzied Member
Re: The Best GGD That Was Ever Made
 Originally Posted by Bonnie West
Excellent work!
BTW, was the original GGD coded in VB Classic? Or, did you have to port it?
I don't know what it was made in. As with most programs that can draw graphics in real time (like change the width and the image INSTANTLY changes) it was likely written in a faster language such as some form of C or C++. Also, the source code for GGD isn't available online anywhere that I have found.
My version runs slower than "real time" when drawing the image, even with the external DLL file it uses to draw the byte array to the picbox, due to the for-next loops that process the image data according to the options buttons that the user has selecte. So yeah, I doubt that any form of BASIC was used to program the original GGD. Also I have no access to its source code, so I made my based on the behavior of GGD, not based on any actual preexisting code. This means every bit of code I wrote I had to write from scratch, and it took a very long long LONG time to write, like a few weeks worth of programming.
Last edited by Ben321; Jul 15th, 2012 at 07:15 PM.
-
Jul 16th, 2012, 01:37 AM
#4
Re: The Best GGD That Was Ever Made
I see...
Well then, thanks for taking the time to improve upon the original GGD. For sure, somebody will find it useful!
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jul 16th, 2012, 04:38 AM
#5
Re: The Best GGD That Was Ever Made
The speed of VB programs can usually be very close to (or even equal to) the speed of C programs, assuming both have been optimised properly (if not, whichever is most optimised will probably be faster).
I picked a random set of loops from your code ("Case 4" of LoadRawImageData), and it is clear that they are unoptimised:
Code:
For BlockY = 0 To HScroll2.Value - 1 Step TileSize
For BlockX = 0 To HScroll1.Value - 1 Step TileSize
For SubY = 0 To TileSize - 1
For SubX = 0 To TileSize - 1
Y = BlockY + SubY
X = BlockX + SubX
ImgData(2, X, HScroll2.Value - 1 - Y) = Pal(RawData(n)) And &HFF
ImgData(1, X, HScroll2.Value - 1 - Y) = (Pal(RawData(n)) And &HFF00&) / &H100&
ImgData(0, X, HScroll2.Value - 1 - Y) = (Pal(RawData(n)) And &HFF0000) / &H10000
n = n + 1
Next SubX
Next SubY
Next BlockX
Next BlockY
(indenting added to make the code much more readable, and make the issues clearer)
The value of Y does not change for different values of SubX, so why calculate it repeatedly inside the SubX loop? You are doing it TileSize times as often as you need to, which can be eliminated by simply moving that line up to the SubY loop.
There are many other things which are being done more often than needed, one of the best examples being the calculation of HScroll2.Value - 1, which presumably doesn't change at all while these loops are running... in which case you are doing it 3 * HScroll1.Value * HScroll2.Value times as often as you need to.
Add in a few other similar things, and it can become this (untested):
Code:
Dim H1 as Long, H2 as Long
Dim PR as Long
Dim TileSizeMinus1 as Long
H1 = HScroll1.Value - 1
H2 = HScroll2.Value - 1
TileSizeMinus1 = TileSize - 1
For BlockY = 0 To H2 Step TileSize
For BlockX = 0 To H1 Step TileSize
For SubY = 0 To TileSizeMinus1
y = H2 - (BlockY + SubY)
For SubX = 0 To TileSizeMinus1
X = BlockX + SubX
PR = Pal(RawData(n))
ImgData(2, X, Y) = PR And &HFF
ImgData(1, X, Y) = (PR And &HFF00&) \ &H100&
ImgData(0, X, Y) = (PR And &HFF0000) \ &H10000
n = n + 1
Next SubX
Next SubY
Next BlockX
Next BlockY
(this may have a minor change of behaviour due to using \ rather than / , so you may want to revert that and sacrifice the speed gain it gives)
For larger values of HScroll1.Value and HScroll2.Value, these changes should make a significant difference to the speed of these loops.
There are likely to be many more optimisations that can be done outside of the loops (including altering the data types of the variables that are used in the loops), even without considering a change of methodology (which often gives very dramatic improvements) or compiler options (which can also be dramatic).
Whether or not the speed can reach the same as an equivalent program is unpredictable (especially when you don't have the code for the other), and how much effort it is worth putting in to optimisation is up to you... in most cases reaching the ultimate speed isn't that important.
By the way, rather than linking to code on an external site, please post it in (or attach it to) your post... that way your thread doesn't become worthless if the other site isn't working, or if they delete/move the file, or someone is behind a company firewall which blocks that site, etc.
-
Jul 19th, 2012, 11:46 AM
#6
Thread Starter
Frenzied Member
Re: The Best GGD That Was Ever Made
 Originally Posted by si_the_geek
The speed of VB programs can usually be very close to (or even equal to) the speed of C programs, assuming both have been optimised properly (if not, whichever is most optimised will probably be faster).
I picked a random set of loops from your code ("Case 4" of LoadRawImageData), and it is clear that they are unoptimised:
Code:
For BlockY = 0 To HScroll2.Value - 1 Step TileSize
For BlockX = 0 To HScroll1.Value - 1 Step TileSize
For SubY = 0 To TileSize - 1
For SubX = 0 To TileSize - 1
Y = BlockY + SubY
X = BlockX + SubX
ImgData(2, X, HScroll2.Value - 1 - Y) = Pal(RawData(n)) And &HFF
ImgData(1, X, HScroll2.Value - 1 - Y) = (Pal(RawData(n)) And &HFF00&) / &H100&
ImgData(0, X, HScroll2.Value - 1 - Y) = (Pal(RawData(n)) And &HFF0000) / &H10000
n = n + 1
Next SubX
Next SubY
Next BlockX
Next BlockY
(indenting added to make the code much more readable, and make the issues clearer)
The value of Y does not change for different values of SubX, so why calculate it repeatedly inside the SubX loop? You are doing it TileSize times as often as you need to, which can be eliminated by simply moving that line up to the SubY loop.
There are many other things which are being done more often than needed, one of the best examples being the calculation of HScroll2.Value - 1, which presumably doesn't change at all while these loops are running... in which case you are doing it 3 * HScroll1.Value * HScroll2.Value times as often as you need to.
Add in a few other similar things, and it can become this (untested):
Code:
Dim H1 as Long, H2 as Long
Dim PR as Long
Dim TileSizeMinus1 as Long
H1 = HScroll1.Value - 1
H2 = HScroll2.Value - 1
TileSizeMinus1 = TileSize - 1
For BlockY = 0 To H2 Step TileSize
For BlockX = 0 To H1 Step TileSize
For SubY = 0 To TileSizeMinus1
y = H2 - (BlockY + SubY)
For SubX = 0 To TileSizeMinus1
X = BlockX + SubX
PR = Pal(RawData(n))
ImgData(2, X, Y) = PR And &HFF
ImgData(1, X, Y) = (PR And &HFF00&) \ &H100&
ImgData(0, X, Y) = (PR And &HFF0000) \ &H10000
n = n + 1
Next SubX
Next SubY
Next BlockX
Next BlockY
(this may have a minor change of behaviour due to using \ rather than / , so you may want to revert that and sacrifice the speed gain it gives)
For larger values of HScroll1.Value and HScroll2.Value, these changes should make a significant difference to the speed of these loops.
There are likely to be many more optimisations that can be done outside of the loops (including altering the data types of the variables that are used in the loops), even without considering a change of methodology (which often gives very dramatic improvements) or compiler options (which can also be dramatic).
Whether or not the speed can reach the same as an equivalent program is unpredictable (especially when you don't have the code for the other), and how much effort it is worth putting in to optimisation is up to you... in most cases reaching the ultimate speed isn't that important.
By the way, rather than linking to code on an external site, please post it in (or attach it to) your post... that way your thread doesn't become worthless if the other site isn't working, or if they delete/move the file, or someone is behind a company firewall which blocks that site, etc.
What does \ do in VB6 that / doesn't do in VB6? I never even saw the \ symbol before. What does it do? Are you referencing something from VB.net? Because you see I'm not using .net, but rather am using VB6 for this.
-
Jul 19th, 2012, 12:14 PM
#7
Re: The Best GGD That Was Ever Made
It is part of VB6, and also VB.Net.
It is just a quicker method of doing whole-number division... a \ b gives the same result as Int(a / b) , but much quicker.
For situations where the end result would be a whole number (eg: 4/2=2) it does not alter behaviour at all, but in situations where it isn't a whole number (eg: 5/2=2.5) it might alter behaviour depending on what you are doing... I haven't checked this situation enough to be sure, but the chances are that if there is a difference then it wont even be noticeable (if it is, it might be ignorable).
-
Aug 13th, 2012, 11:50 AM
#8
Thread Starter
Frenzied Member
Re: The Best GGD That Was Ever Made
So int(a/b) is slower than a\b. But how does a\b compare to just a/b. If my input numbers are integers, and the output is also going to be an integer based on the selection of input numbers (such as 4/2), which is faster 4/2 or 4\2? I'm guessing that since 4\2 doesn't have to worry about decimal point handling and such stuff (it simply drops any part of the output isn't in the integer part of the number), that 4\2 might be faster. Please let me know. Thanks.
-
Aug 13th, 2012, 12:00 PM
#9
Thread Starter
Frenzied Member
Re: The Best GGD That Was Ever Made
Also I think C does go faster for example in VB6, to set B = A and then increment A by 1, in VB6 you would use:
Code:
Dim A as Integer: Dim B as Integer
B = A
A = A +1
This can NOT be further optimized
In C, this looks like:
Code:
Int A, B;
B = A;
A = A + 1;
However the C code CAN be optimized:
These 2 lines of code takes the time need to run only 2 lines of code, but performs THREE LINES of code worth of actions.
Allocate memory for each variable
Set B to current value of A
Increment value of A
That's the difference between C and VB. C can be a lot more optimized.
-
Aug 13th, 2012, 12:20 PM
#10
Re: The Best GGD That Was Ever Made
 Originally Posted by Ben321
So int(a/b) is slower than a\b. But how does a\b compare to just a/b. ... I'm guessing that since 4\2 doesn't have to worry about decimal point handling and such stuff (it simply drops any part of the output isn't in the integer part of the number), that 4\2 might be faster. Please let me know. Thanks.
\ is noticeably faster
 Originally Posted by Ben321
Also I think C does go faster for example in VB6, to set B = A and then increment A by 1, in VB6 you would use:
Code:
Dim A as Integer: Dim B as Integer
B = A
A = A +1
This can NOT be further optimized
Yes it can... change Integer to Long.
However, for something that simple, optimisation is clearly rather pointless.
These 2 lines of code takes the time need to run only 2 lines of code, but performs THREE LINES of code worth of actions.
The number of lines of code is no indicator of optimisation, what matters is the number of CPU clock cycles.
For example, "DoEvents" is a rather simple line of code, but can easily take 200 milliseconds or more, whereas your A and B example should take under 1.
As a general guideline, well optimised code usually has more lines than the unoptimised equivalent (just not for ridiculously simple examples). Shorter code is not the same thing as faster code.
As for your comments about C, in order to determine whether or not the A++ version is more optimised, you would need to look at the machine code that is generated... and a decent C compiler should produce exactly the same machine code for both methods you used, in which case the A++ version is not any more optimised at all, it is just fewer lines of code in the IDE.
As a side note for you to think about, it is no secret that when VB6 compiles your code, it uses a slightly modified version of a decent C compiler. You don't have all the abilities of C inside a VB program, but you have most of them, and lots of extra useful bits.
Last edited by si_the_geek; Aug 13th, 2012 at 12:40 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|