Community
General and Everything Else => The Games and other Sierra Adventure stuff => Topic started by: Kawa on August 15, 2015, 03:21:18 PM
-
In my collection, I have exactly one game that has AVI cutscenes: King's Quest 6 CD. For a laugh, I copied HDLOGO.AVI to my SCI Companion scratchpad and removed most of the logo stuff from the title screen, repalcing that with a simple ShowMovie(0 "hdlogo.avi"), then restoring the usual palette in the next state and all that. That works, no problem. So I made it play TOON.AVI, confirming that Media Player Classic doesn't like MS Video 1 files with (certain kinds of) palette changes.
Turns out ffmpeg can't encode to MS Video 1, but luckily I have content creation programs that can export to AVI, including the option to use MS Video 1...
Unknown tag '....' found!
Oh. What '....' though? There's no such thing in this file, as far as I can see. :-\
Fun exercise: look closely at the JUNK chunks in KQ6CD's HDLOGO.AVI file.
-
Note that the AVI intro was only used in the Win version. There are a few SCI games that used AVIs, but they are either Win interpreters or SCI2+. GK1 (Win), GK2 demo (Win only), KQ7 (Win), QfG4 (Win). The DOS versions of these used SEQ, or in the case of KQ7, RBT. An AVI to SEQ converter might be nice to have.
-
Note that the AVI intro was only used in the Win version.
I know. That's why I went in expecting it to only work at all in ScummVM. And with the KQ6 videos, it did.
And yeah, I suppose it would be nice to have a way to make SEQ files.
-
Unknown tag '....' found!
Oh. What '....' though? There's no such thing in this file, as far as I can see. :-\
The tag2str routine substitutes dots if the actual character is not printable ASCII. Sort of like hex editors do.
It could be due to a bug in the AVI file parser (which is shared by all of ScummVM) or a corrupted file of some sort.
-
I most sincerely doubt it's the latter.
-
I believe I have found and fixed the issue that made my sample movie play discolored outside of SeqLab and ScummVM. From studying OmerMor's interpreter source, specifically movie.h, I have identified some critical fields that needed to be set. The only remaining issue was that you're not supposed to use the last three colors in SCI16+.
The download in the stash (check my signature) has been updated, both in the "sets the critical fields" sense and the "book example frames don't use reserved colors" sense.
Full disclosure: I've only tested this on SCI16, not SCI11 or ScummVM.
-
Great news!
OmerMor's interpreter source
Last I checked it was Sierra's source... :P
-
btw, I'm pretty sure SCI16 refers to "16 bit SCI", not version 1.6.
-
That was the way I took it, too.
-
I call it that to distinguish it from regular in-the-wild no-debugger SCI11.
-
for (var frame = 0; frame < 16; frame++)
That is a very bad bug and I should be ashamed of myself.
Fixed version below, obviously.
-
Fixed version below, obviously.
Is it though?
-
Should be in the stash that's linked in my sig.
Oh, here's a before and after:
Before (http://i.imgur.com/eStG4Qi.png), with the <16 bug.
During (http://i.imgur.com/Iu1Uda6.gif), with a resource size limit straddling view, coincidentally sixteen frames.
After (http://i.imgur.com/6U7wBVB.gif), with the boot hand included so you know it's not a bullshot.
Big update!
SeqMaker now has left-right difference windowing as well as top-bottom. That is, stored lines are no longer always 320 pixels long. This reduces day1.seq from 1.09 MB to only 608 KB, with no loss of actual content! The only way this could be made smaller is if it supported compression, but only my player does that. 8)
-
How about making it a plugin for Companion?
-
I'd think some kind of UI would be required for that haha
-
Great job kawa!
I think it should be integrated into SCI Companion, but I guess it's in C# so I guess not.
-
The code is simple enough. On the other hand, I've found C#'s standard library (or .Net's, I guess?) to be somewhat easier to work with than C++'s.
And then there's Managed C++.
-
No problem. It would not have to too elaborate. If you don't mind I could play around with it.
-
This would be a fantastic addition to Companion.
-
Gonna need some kinda GUI though :3
-
So I was kicking this around. Very rough first attempt, but it works. I combined your player and maker in a Win Form. You can load the source images by clicking the 'Add' button or dragging and dropping in the listbox. Items can be rearranged by dragging and dropping within the listbox or selecting an item and using the 'up' or 'down' buttons. The out file can be set in the SEQ name box at the bottom. When you have the files added and an out name set, just click the 'Make SEQ' button.
You can view the resulting SEQ file by selecting it from the open button on the tool bar and clicking the play button.
What need to be done is to adjust Kawa's code to allow for using a different order and possibly unnumbered input names. For now it will just use the same location of the in files for the output folder, but this should be by the path passed from Companion, possibly in a "SEQ" sub folder, since this is where Sierra usually placed them. The player controls were just pasted in from another project of mine. I will probably delete the volume slider, but I am kicking around the idea of having it play the aud and or snd resource(s) that would be used in game to be able to check audio sync. This might be more trouble than it is worth.
If there is any interest in this I can put it up on my Bitbucket account after I get it cleaned up and a little more tested.
-
I'm sorry if I was stepping on your toes with your code, Kawa, but if you do not want me working with your project and if there is no interest by others, I do not want to invest much more time into this.
-
For the player I literally preprocessed ScummVM's code, and for the converter, I'd actually welcome another contributor... albeit mostly with regards to RLE compression, see if that car video can get any smaller XD
Nah seriously though go nuts.
-
This is brilliant! That'll aid some fancy touches to game making quite nicely! :)
-
OK, I'll clean it up and put it on my GIT. Perhaps over the weekend. Perhaps it could become a community effort. Might be nice to add an animated GIF import.
-
Here is a build in its current form, warts and all. It is a bit buggy. Just drop it in a folder inside of Companion's Plugin folder. Load a project and call it from Companion's Plugin Plugin menu.
-
I have it so that it will add frames in order of the sequence in the listbox so that the user can order them as needed. This means that there is no need to number the file names other than for the user's convenience. Selecting an image in the listbox will display it in the picturebox on the right side if there is no SEQ file loaded.
I would like to add support for other image formats like PCX and GIF, but these are no supported by .NET. Does anyone have a suggestion for a wrapper?
Also, what does anyone think about having the tool automatically adding the "movieDir=" entry in the CFG file?
-
PCX oughta be easy enough. You'll notice my encoder doesn't use .Net's Image classes, but reads the bitmaps raw. A wrapper would not be impossible to produce, handling things like BMP's upside-downness and PCX's RLE and just passing raw 320x200 pixmaps to the encoder... and maybe a PCX-to-Sys.Draw.Bitmap method for display XD
-
It does not like PCX as is. Your CheckValid method cannot determine the size. If I skip it, it will generate the SEQ, but it is all scrambled. Also you cannot load PCX or GIF images in a .NET picturebox without a wrapper. I'll try to upload the project later tonight or tomorrow and you tale a look if you want.
-
Shelving the additional formats for now. I was trying to make the GUI a little more complete. I added a FlowLayoutPanel to display a thumbnail for each image. These are in the same order as the list. If the list is reordered or if an image is removed or a new image is added, the order of the thumbnails will reflect the change. This will give an at-a-glance view of the frame order.
The "Use SEQ Subdirectory" checkbox will let the user set the output to a subdirectory named 'SEQ' under the project's folder. Deselecting it will set the output to the project's base folder.
-
It does not like PCX as is. Your CheckValid method cannot determine the size. If I skip it, it will generate the SEQ, but it is all scrambled. Also you cannot load PCX or GIF images in a .NET picturebox without a wrapper. I'll try to upload the project later tonight or tomorrow and you tale a look if you want.
What do you think I was trying to say?
-
I know what you said, I was just mulling over reasons for bothering with a wrapper.
-
Here is a current build. I have a git setup on Bitbucket. It is private for now. Anyone that wants access PM me an email for an invite.
-
Why bother with a wrapper? Because System.Drawing doesn't like PCX and I like a challenge.
I wonder if one can get palette indices from a System.Drawing.Bitmap's image data... like, if you have an image -- a BMP, PNG, or GIF -- with three black entries in its palette, can you tell that this black pixel is color #2 and this other black pixel is color #3? Cos that's the kind of uncertainty that made me read BMP files by hand in this project.
Update: okay, so you can in fact get that data from a Bitmap, through LockBits of all methods. Nasty, and it only plays nice (and to our needs) on 8-bit images... but then why would you put a 4-or-less-bit image in there, hmm? But, the cool part is, besides the lack of PCX support, you can just load whatever System.Drawing supports and see if PixelFormat == PixelFormat.Format8bppIndexed. From then on, things like PNG/GIF compression and BMP being upside-down don't matter. So if I were to make a wrapper and add PCX support, I'd lockbit up a copy of the raw pixels for those three, and return the same manually for PCX.
Update: I now have a method that, given a filename, a 64000-byte target array, and an optional 768-byte palette array, returns the same right-side-up raw pixel data for any 256-color image that System.Drawing supports, plus PCX.
-
For the GUI it needs to be able to be displayed in a WinForms PictureBox. Do you want me to just use the same email you used for the Wiki for the git?
-
All but PCX can of course be used directly in a PictureBox simply by setting the relevant property to your Bitmap object:
pictureBox.Image = new Bitmap("frame.bmp");
Which inspires me to make a PCX-to-Bitmap method. Done.
Also, git doesn't like me.
-
You don't have to setup git on your machine, but I send you an invite and you can download a zip of the project so we can be working from the same code.
-
Not sure which IDE you're using, but VS Community 2013 has pretty seamless integration with git.
-
I use 2010 Express primarily, but I got a copy of 2013, I forget which but it's the free one, to try and compile SCI Companion.
-
So, have you done anything with it? If you are not going to use the git, can I somehow get what you have have, so far?
-
Mercurial is okay with me. But all I have is my little helper methods to grab the pixel and pal data, and to allow loading from PCX. I can put it right here later today if you want it.
-
Sure. Right now I am implementing a save file method, which I think might be nice to have for larger projects.
-
Saving to what?
-
An XML file. Just to keep track of all of the input images and the order so you do not have to sort them every time you want to work on it or make changes.
-
That's a good call. Incidentally, I have a JSON library that I wrote.
-
Finished the save file class. I'll do a file association so a project can be loaded by double clicking the save file. While I am at it, I'll add an option to associate SEQ files with the player to open a SEQ to play, too.
-
Moved the thumbnails to the bottom to make it not so wide. Add images with the "Add" button or dropping them into the list. It works with PCX now, but the MakeSeq method still does not work with GIF. Edit any image on the fly by right clicking on an item in the list or its corresponding thumbnail and selecting "Edit". Drag and drop frames in the list to rearrange frame order. Once there are at least 2 frames loaded and a SEQ name entered you can create your new SEQ. It will automatically load it in the player. To view it, just click the "Play" button.
Possible future features:
- Parse/Convert animated GIFs? AVIs?
- Export SEQ to animated GIF? Series of BMP/GIF/PCX files?
- Get first frame of SEQ to display on SEQ load in player
- Add save prompt
Attached is a build of the current state. Add it to Companion's Plugins folder. Note that this is still a WIP, but feedback is welcomed.
-
Now available: SeqMaker 2.0
http://helmet.kafuka.org/sci/seqmaker2.zip (http://helmet.kafuka.org/sci/seqmaker2.zip)
Features:
? Supports PNG, BMP, GIF, and PCX (no shit!)
? Automatically detects sequences, so you can just drop book1.bmp on it and expect it to make book.seq with all 16 frames.
? Specify a later frame to start from there instead.
? Also supports TXT files with file lists in 'em in place of the first frame.
? Integrated player -- drop a SEQ file on it.
? Player doesn't use SetPixel any more!
? Anything wrong? This even has return codes for integration into UI fronts or whatever.
For command line use:
seqmaker [infile] => as above
seqmaker [infile] -o [outfile] => don't guess the name of the seq to make
seqmaker [seqfile] => play seq in 320x200
seqmaker [seqfile] -d => play seq in 640x400
seqmaker [seqfile] -a => play seq in 320x240
seqmaker [seqfile] -a -d => play seq in 640x480
-
Source?
-
Well okay. ::)
-
I am not sure of why the rolly smiley. If you do not want me to incorporate your code into the GUI, just let me know. I can leave it to you to do a GUI.
-
The eye roll? Because I'm a dramatic sarcastic piece of trash, nothing serious to it. And to think I made this specifically so it could be invoked from a GUI... except maybe the player, in that it wouldn't be a panel in one's GUI, but its own window...
-
Awesome!
Also, *its. Because I'm a grammar nazi.
-
OK, I guess I was reading something into it that was not intended. I just didn't want to be stepping on anyone's toes.
-
Here is the latest build. It has improved drag and drop functionality, an animated GIF import, a save project system and if you associate SEQ files with it, double clicking on a SEQ file will automatically play the file in the player. Please give feedback if you try it.
-
For the GUI I went back to your original code for the player as there seems to be palette issues with the new player. It plays Sierra SEQ files properly, but not new ones. Attached is a screen from a SEQ made with your SeqMaker2 from the original BMPs played in the player in SeqMaker2.
-
Also, here is a SEQ converted from importing an ani GIF with the GUI.
-
The new player seems to play http://helmet.kafuka.org/sci/theend.seq (http://helmet.kafuka.org/sci/theend.seq) just fine here, as does a freshly-made copy from SeqMaker 1's example data.
-
SeqMaker 2.1 is now available from the usual place. Newly added: exploding a SEQ file into individual bitmaps of your chosen format.
seqmaker cd6.seq -- plays Alexander approaching the mirror
seqmaker cd6.seq -e -- plays, but also saves frames as cd6-0001.png through cd6-0130something.png
seqmaker cd6.seq -e alexmirror1.png -- saves as alexmirror1.png and so on.Aspect and Dual switches have no bearing on what is saved.
-
This is fantastic, guys. Great program.
-
This is fantastic, guys. Great program.
Which one? :D
-
Yeah, there are two. The heart of my GUI program uses Kawa's code. I had nothing to do with his command line version.
-
I almost hate to ask, but source for the new version?
-
I almost hate to provide.
You'll notice there's a new feature in this which isn't in the precompiled version: -x switch on playback, acts as shown.
-
Is this to display the pixel changes between frames?
-
It appears to be that, yes.
In other news, just SysWinDrawing won't cut it if I want to explode animated GIFs -- they're converted to 24bpp, which my toolkit then refuses to work with. I suppose if I really want to support that, I could maybe write my own GIF reader?
-
If by explode you mean to dump all individual images in an animated GIF, I came up with this method:
Image[] getFrames(Image aniGIF)
{
int numFrames = aniGIF.GetFrameCount(FrameDimension.Time);
Image[] frames = new Image[numFrames];
for (int i = 0; i < numFrames; i++)
{
aniGIF.SelectActiveFrame(FrameDimension.Time, i);
frames[i] = ((Image)aniGIF.Clone());
}
return frames;
}
and called with:
Image[] frames = getFrames(Image.FromFile(aniGIFPath));
Given that this dumps them as GIFs they stay 8-bit paletted. As long as the animated GIF is 320x200, it seems to work flawlessly for dumping images ready for converting to a SEQ.
-
...You didn't "come up" with that. That's one of the search results, you cad.
But whatever, I'll try again tomorrow.
And we're back awake. Happy Saturday everyone! Now, loading a non-animated GIF like this
using (var maybeAnim = new Bitmap(filename))and looking at maybeAnim in debug reveals that its PixelFormat to be Format8bppIndexed, which is good. Loading an animated gif -- the one attached, in fact -- reveals it to be Format32bppArgb. Indeed, extracting a frame with
var newFrame = ((Bitmap)maybeAnim.Clone()); and looking at newFrame.PixelFormat reveals it too to be 32-bit.
I know it's not a quirk of the input image -- this forum's Marquee toolbar button ((http://sciprogramming.com/community/Themes/MTBlue/images/bbc/move.gif)) and the last-seen Tumblr Radar also do this.
-
...You didn't "come up" with that. That's one of the search results, you cad.
Oh spare me the attitude. I never claimed that I wrote it from scratch. Actually it came from another project of mine that was the result of yes, Google ::) and experimentation.
-
Next time I want to be sarcastic, I'll try to find even more old-fashioned things to call you, okay? :)
-
I figured there's a few ways to load an image. I like to use x = new Bitmap(file), but there's also y = Bitmap.FromFile(file) (which oddly returns an Image, not a Bitmap, hence my preference), and z = Image.FromFile(file) plus a few that don't use filenames. So I thought, what if this causes my animated gifs to load as anything but 8bpp indexed?
So I wrote a quick test program that loads two different gifs, attached below, in three different ways, and reports on their PixelFormat properties.
Unsurprisingly, the one returns an image with PixelFormat.Format8bppIndexed, and the other is always PixelFormat.Format32bppArgb.
How, then, does this line from Collector's SEQTool apparently return 8bpp images?
Image[] frames = getFrames(Image.FromFile(aniGIFPath));
-
That is just calling the method I posted above. It is just cloning each frame in the ani GIF. Of course I am writing each to a file so they can be easily edited.
-
I'm rightfully angry now. Last time I tried to explode a gif and save the individual frames, Image.Save used the wrong format -- the .gif files were secretly PNG. Yet somehow,
var img = Bitmap.FromFile("ArArea5R.gif");
Console.WriteLine(img.PixelFormat); //<-- Format32bppArgb
img.SelectActiveFrame(FrameDimension.Time, 1);
var frame = ((Image)img.Clone());
Console.WriteLine(frame.PixelFormat); //<-- Format32bppArgb
frame.Save("ArArea5R_A.gif");
var newimg = Bitmap.FromFile("ArArea5R_A.gif");
Console.WriteLine(newimg.PixelFormat); //<-- Format8bppIndexed
On the other hand, there's always the possibility of GIF files to have per-frame palettes to make me feel a little better.
-
That's not surprising to me. I think the Image stuff in the .net libraries is wraps gdiplus for a lot of it's functionality. That's what Companion used to use for loading gifs, but it wouldn't always give me an 8-bit indexed image (it depended on the particular gif). So I ended up switching to a 3rd party library to load gifs.
-
That's not surprising to me. I think the Image stuff in the .net libraries is wraps gdiplus for a lot of it's functionality.
Correct! Also, I should get one of the earlier gifs I tried to load, see what happens when I try to save a frame from those.
Cos I distinctly remember trying to save to a file with one type's extension, only to get the other unless I explicitly specified an ImageFormat. Hence my toolkit's inclusion of an extension method that guesses the ImageFormat from the extension given. Yet in the experiment earlier today I got perfectly valid gif files.
Update: Collector, I despise you so much right now. Know that this feeling will pass as I sleep. I didn't change a single line of code in SeqMaker2, nor even in the project settings -- it still used "giphy2.gif" as the command line parameters. Not one thing, and yet... well, see the attachment. Good night, everyone.
-
So here's my thoughts on how to handle compression. My player can handle it just fine, using ScummVM as a guide, but I've always been afraid of doing the reverse...
We have the following commands:
- 0xC0 - top two bits set: clear out the top two bits. If zero, end this line. If not, skip that many bytes on the current line.
- 0x80 - only the top bit set: clear out the top two bits. If zero, copy raw bytes to finish the rest of the line. If not, copy that many raw bytes.
- Something that I can't quite express like that: a 16-bit value, small part is the command, large part the count.
- 2: Skip bytes.
- 3: Copy raw bytes.
- 6: Copy entire lines.
- 7: Skip entire lines.
Okay, so here's my theory on how to produce compressed SEQ frame data:
First, crop out the frame as before. Obviously.
Second, if this is not the first frame, compare each run of pixels with the previous frame's and keep track of them in Run objects. Say you find one different pixel, you instantiate a new CopyRun with its Start set to the current column and Length set to 1, and add it to currentLine. Continue looking, and the next pixel is also different, so you increase currentRun.Length. Then you find a pixel that's the same as the previous frame's, so you start a SkipRun and do pretty much the same as before until you find the end of the current line. Continue with the next line until done. You should now have a series of Runs that cover the entire (cropped) frame:
currentFrameRunLines = [
[ CopyRun(0, 10), SkipRun(10, 12) ... ] //lengths total should equal frame width
[ SkipRun(0, 2), CopyRun(2, 8) ... ]
... //line total should equal frame height
]
If this -was- the first frame, just store it fully raw as we do now.
Third, run through each line to emit the actual compressed frame data. Pick between 8-bit and 16-bit blocks where appropriate. If a run happens to reach the end of a line, emit the bytes to skip to the end. If a run spans the entire frame width, check if there's more such runs after and emit a "copy/skip entire lines" command.
I would personally build it up, as it were, doing only 8-bit commands at first and adding 16-bit support after. It seems safer.