Added video assets
Added all video assets encoded as GIF files and included the packvideo tool that will compress the art into the IIgs native format. Binaries for Mac and PC are supplied
BIN
assets/death/death07.gif
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
assets/death/death09.gif
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
assets/death/death10.gif
Normal file
After Width: | Height: | Size: 105 KiB |
BIN
assets/death/death12.gif
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
assets/death/death13.gif
Normal file
After Width: | Height: | Size: 376 KiB |
BIN
assets/death/death15.gif
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
assets/death/death18.gif
Normal file
After Width: | Height: | Size: 153 KiB |
BIN
assets/death/death19.gif
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
assets/death/death22.gif
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
assets/death/death27.gif
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
assets/death/death28.gif
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
assets/death/death34.gif
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
assets/death/death36.gif
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
assets/death/death39.gif
Normal file
After Width: | Height: | Size: 208 KiB |
BIN
assets/movie/video01.gif
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
assets/movie/video02.gif
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/movie/video03.gif
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
assets/movie/video04.gif
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
assets/movie/video05.gif
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/movie/video06.gif
Normal file
After Width: | Height: | Size: 359 KiB |
BIN
assets/movie/video07.gif
Normal file
After Width: | Height: | Size: 564 KiB |
BIN
assets/movie/video08.gif
Normal file
After Width: | Height: | Size: 480 KiB |
BIN
assets/movie/video09.gif
Normal file
After Width: | Height: | Size: 921 KiB |
BIN
assets/movie/video10.gif
Normal file
After Width: | Height: | Size: 226 KiB |
BIN
assets/movie/video11.gif
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
assets/movie/video12.gif
Normal file
After Width: | Height: | Size: 309 KiB |
BIN
assets/movie/video13.gif
Normal file
After Width: | Height: | Size: 333 KiB |
BIN
assets/movie/video14.gif
Normal file
After Width: | Height: | Size: 321 KiB |
BIN
assets/movie/video15.gif
Normal file
After Width: | Height: | Size: 364 KiB |
BIN
assets/movie/video16.gif
Normal file
After Width: | Height: | Size: 352 KiB |
BIN
assets/movie/video17.gif
Normal file
After Width: | Height: | Size: 303 KiB |
BIN
assets/movie/video18.gif
Normal file
After Width: | Height: | Size: 721 KiB |
BIN
assets/movie/video19.gif
Normal file
After Width: | Height: | Size: 457 KiB |
BIN
assets/movie/video20.gif
Normal file
After Width: | Height: | Size: 300 KiB |
BIN
assets/movie/video21.gif
Normal file
After Width: | Height: | Size: 411 KiB |
BIN
assets/movie/video22.gif
Normal file
After Width: | Height: | Size: 309 KiB |
BIN
assets/movie/video23.gif
Normal file
After Width: | Height: | Size: 360 KiB |
BIN
assets/movie/video24.gif
Normal file
After Width: | Height: | Size: 470 KiB |
BIN
assets/movie/video25.gif
Normal file
After Width: | Height: | Size: 442 KiB |
BIN
assets/movie/video26.gif
Normal file
After Width: | Height: | Size: 363 KiB |
BIN
assets/movie/video27.gif
Normal file
After Width: | Height: | Size: 348 KiB |
BIN
assets/movie/video28.gif
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
assets/movie/video29.gif
Normal file
After Width: | Height: | Size: 204 KiB |
BIN
assets/movie/video30.gif
Normal file
After Width: | Height: | Size: 174 KiB |
BIN
assets/movie/video31.gif
Normal file
After Width: | Height: | Size: 289 KiB |
BIN
assets/movie/video32.gif
Normal file
After Width: | Height: | Size: 213 KiB |
BIN
assets/movie/video33.gif
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
assets/movie/video34.gif
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
assets/movie/video35.gif
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
assets/movie/video36.gif
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
assets/movie/video37.gif
Normal file
After Width: | Height: | Size: 251 KiB |
BIN
assets/movie/video38.gif
Normal file
After Width: | Height: | Size: 253 KiB |
BIN
assets/movie/video39.gif
Normal file
After Width: | Height: | Size: 131 KiB |
BIN
assets/movie/video40.gif
Normal file
After Width: | Height: | Size: 213 KiB |
BIN
assets/movie/video41.gif
Normal file
After Width: | Height: | Size: 431 KiB |
BIN
assets/movie/video42.gif
Normal file
After Width: | Height: | Size: 214 KiB |
BIN
assets/movie/video43.gif
Normal file
After Width: | Height: | Size: 246 KiB |
BIN
assets/movie/video44.gif
Normal file
After Width: | Height: | Size: 139 KiB |
BIN
assets/movie/video45.gif
Normal file
After Width: | Height: | Size: 165 KiB |
BIN
assets/movie/video46.gif
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
assets/movie/video47.gif
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
assets/movie/video48.gif
Normal file
After Width: | Height: | Size: 123 KiB |
BIN
assets/movie/video49.gif
Normal file
After Width: | Height: | Size: 118 KiB |
89
assets/prebuild.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import burger
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copy movies and audio from a folder
|
||||||
|
# Convert .wav files to 4 bit audio
|
||||||
|
#
|
||||||
|
|
||||||
|
def convertdata(soundexename,videoexename,srcfolder,destfolder):
|
||||||
|
filelist = os.listdir(srcfolder)
|
||||||
|
error = 0
|
||||||
|
for item in filelist:
|
||||||
|
|
||||||
|
#
|
||||||
|
# If a sound file, convert to 4 bits per sample
|
||||||
|
if item.lower().endswith('.wav'):
|
||||||
|
src = os.path.join(srcfolder,item)
|
||||||
|
dest = os.path.join(destfolder,item[:-4])
|
||||||
|
|
||||||
|
# Only if newer
|
||||||
|
if burger.isthesourcenewer(src,dest)==True:
|
||||||
|
cmd = soundexename + ' -s "' + src + '" "' + dest + '"'
|
||||||
|
error = subprocess.call(cmd,cwd=srcfolder,shell=True)
|
||||||
|
elif item.lower().endswith('.gif'):
|
||||||
|
|
||||||
|
# Copy any other file as is
|
||||||
|
src = os.path.join(srcfolder,item)
|
||||||
|
dest = os.path.join(destfolder,item[:-4])
|
||||||
|
|
||||||
|
# Only if newer
|
||||||
|
if burger.isthesourcenewer(src,dest)==True:
|
||||||
|
cmd = videoexename + ' -v "' + src + '" "' + dest + '"'
|
||||||
|
error = subprocess.call(cmd,cwd=srcfolder,shell=True)
|
||||||
|
|
||||||
|
# Abort on error
|
||||||
|
if error!=0:
|
||||||
|
break
|
||||||
|
|
||||||
|
return error
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copy the data files for Space Ace for the Apple IIgs
|
||||||
|
#
|
||||||
|
|
||||||
|
def main(workingDir):
|
||||||
|
|
||||||
|
#
|
||||||
|
# Make sure the tool is built
|
||||||
|
#
|
||||||
|
|
||||||
|
toolfolder = os.path.dirname(workingDir)
|
||||||
|
destfolder = os.path.join(toolfolder,'bin')
|
||||||
|
toolfolder = os.path.join(toolfolder,'tools','bin')
|
||||||
|
soundexename = burger.gettoolpath(toolfolder,'packsound',True)
|
||||||
|
videoexename = burger.gettoolpath(toolfolder,'packvideo',True)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Prepare for the output
|
||||||
|
#
|
||||||
|
|
||||||
|
burger.createfolderifneeded(destfolder)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copy the data files
|
||||||
|
#
|
||||||
|
|
||||||
|
srcfolder = os.path.join(workingDir,'movie')
|
||||||
|
error = convertdata(soundexename,videoexename,srcfolder,destfolder)
|
||||||
|
|
||||||
|
if error!=0:
|
||||||
|
return error
|
||||||
|
|
||||||
|
srcfolder = os.path.join(workingDir,'death')
|
||||||
|
error = convertdata(soundexename,videoexename,srcfolder,destfolder)
|
||||||
|
|
||||||
|
return error
|
||||||
|
|
||||||
|
#
|
||||||
|
# If called as a function and not a class,
|
||||||
|
# call my main
|
||||||
|
#
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(os.path.dirname(os.path.abspath(__file__))))
|
BIN
tools/bin/macosx/packvideo
Normal file
BIN
tools/bin/windows/x64/packvideo.exe
Normal file
BIN
tools/bin/windows/x86/packvideo.exe
Normal file
20
tools/packvideo/packvideov10win.sln
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual Studio 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "packvideo", "packvideov10win.vcxproj", "{298BD960-7986-3C55-B5AD-FA4882378687}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{298BD960-7986-3C55-B5AD-FA4882378687}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{298BD960-7986-3C55-B5AD-FA4882378687}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{298BD960-7986-3C55-B5AD-FA4882378687}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{298BD960-7986-3C55-B5AD-FA4882378687}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
35
tools/packvideo/packvideov10win.vcxproj
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectName>packvideo</ProjectName>
|
||||||
|
<FinalFolder>..\bin\windows\</FinalFolder>
|
||||||
|
<ProjectGuid>{298BD960-7986-3C55-B5AD-FA4882378687}</ProjectGuid>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<Import Project="$(SDKS)\visualstudio\burger.toolv10.props" />
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings" />
|
||||||
|
<ImportGroup Label="PropertySheets" />
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="source\packvideo.h" />
|
||||||
|
<ClCompile Include="source\packvideo.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets" />
|
||||||
|
</Project>
|
14
tools/packvideo/packvideov10win.vcxproj.filters
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="source\packvideo.h">
|
||||||
|
<Filter>source</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="source\packvideo.cpp">
|
||||||
|
<Filter>source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<Filter Include="source">
|
||||||
|
<UniqueIdentifier>{F9C0B66D-A848-3A46-B9E2-1839ABB3C0FD}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
231
tools/packvideo/packvideoxc3osx.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 45;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
32FAA769BE0CBB7413D8E026 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB663B78C243F425CB5F622D /* IOKit.framework */; };
|
||||||
|
646F915E3F985ADB46A990BF /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60566A081602146F3C8BA8CA /* Carbon.framework */; };
|
||||||
|
7E73C42571ABE93C5DE5E7A6 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6061B328817055E8B2E193D6 /* AppKit.framework */; };
|
||||||
|
A612344A435E24A2F1356957 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BBF96056AA4E7B57C08772 /* Cocoa.framework */; };
|
||||||
|
A9CAC7BF34E647803EDD7969 /* packvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F25D9D46BDE3147E8090A574 /* packvideo.cpp */; };
|
||||||
|
EE12FD4C543A29B3691EB5E0 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AC54CC47F3C0DD9956B9AD3 /* OpenGL.framework */; };
|
||||||
|
FF4F14B568DF5EF194A9F6BE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 957F7268BCFABFC0E258709B /* QuartzCore.framework */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXBuildRule section */
|
||||||
|
BFB0BCC60AAC4EB459F83323 /* PBXBuildRule */ = {
|
||||||
|
isa = PBXBuildRule;
|
||||||
|
compilerSpec = com.apple.compilers.proxy.script;
|
||||||
|
filePatterns = "*.glsl";
|
||||||
|
fileType = pattern.proxy;
|
||||||
|
isEditable = 1;
|
||||||
|
outputFiles = (
|
||||||
|
"${INPUT_FILE_DIR}/${INPUT_FILE_BASE}.h",
|
||||||
|
);
|
||||||
|
script = "${SDKS}/macosx/bin/stripcomments ${INPUT_FILE_PATH} -c -l g_${INPUT_FILE_BASE} ${INPUT_FILE_DIR}/${INPUT_FILE_BASE}.h";
|
||||||
|
};
|
||||||
|
/* End PBXBuildRule section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
04BBF96056AA4E7B57C08772 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||||
|
2791201414FE21A0208E5633 /* packvideo */ = {isa = PBXFileReference; explicitFileType = compiled.mach-o.executable; includeInIndex = 0; path = packvideo; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
53A745DDC21ECBC748B26AF9 /* burger.toolxcoosx.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = burger.toolxcoosx.xcconfig; path = xcode/burger.toolxcoosx.xcconfig; sourceTree = SDKS; };
|
||||||
|
60566A081602146F3C8BA8CA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
||||||
|
6061B328817055E8B2E193D6 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||||
|
957F7268BCFABFC0E258709B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||||
|
9AC54CC47F3C0DD9956B9AD3 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
|
||||||
|
AF85042913E5C407EFA05C50 /* packvideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = packvideo.h; path = source/packvideo.h; sourceTree = SOURCE_ROOT; };
|
||||||
|
CB663B78C243F425CB5F622D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
|
||||||
|
F25D9D46BDE3147E8090A574 /* packvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = packvideo.cpp; path = source/packvideo.cpp; sourceTree = SOURCE_ROOT; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
507B15D31C90EF8682AFB59C /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7E73C42571ABE93C5DE5E7A6 /* AppKit.framework in Frameworks */,
|
||||||
|
646F915E3F985ADB46A990BF /* Carbon.framework in Frameworks */,
|
||||||
|
A612344A435E24A2F1356957 /* Cocoa.framework in Frameworks */,
|
||||||
|
32FAA769BE0CBB7413D8E026 /* IOKit.framework in Frameworks */,
|
||||||
|
EE12FD4C543A29B3691EB5E0 /* OpenGL.framework in Frameworks */,
|
||||||
|
FF4F14B568DF5EF194A9F6BE /* QuartzCore.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
4CE489F4A9041625DE5927C3 /* source */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
F25D9D46BDE3147E8090A574 /* packvideo.cpp */,
|
||||||
|
AF85042913E5C407EFA05C50 /* packvideo.h */,
|
||||||
|
);
|
||||||
|
path = source;
|
||||||
|
sourceTree = SOURCE_ROOT;
|
||||||
|
};
|
||||||
|
6555983C4FFDAFC88D6ED936 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
6061B328817055E8B2E193D6 /* AppKit.framework */,
|
||||||
|
60566A081602146F3C8BA8CA /* Carbon.framework */,
|
||||||
|
04BBF96056AA4E7B57C08772 /* Cocoa.framework */,
|
||||||
|
CB663B78C243F425CB5F622D /* IOKit.framework */,
|
||||||
|
9AC54CC47F3C0DD9956B9AD3 /* OpenGL.framework */,
|
||||||
|
957F7268BCFABFC0E258709B /* QuartzCore.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
945D7BCE010E10DA41ABD532 /* packvideo */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
6555983C4FFDAFC88D6ED936 /* Frameworks */,
|
||||||
|
9796CE949CD3951E99BB35F6 /* Products */,
|
||||||
|
4CE489F4A9041625DE5927C3 /* source */,
|
||||||
|
53A745DDC21ECBC748B26AF9 /* burger.toolxcoosx.xcconfig */,
|
||||||
|
);
|
||||||
|
name = packvideo;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9796CE949CD3951E99BB35F6 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
2791201414FE21A0208E5633 /* packvideo */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
56EF2BB6F86F47504C45BD06 /* packvideo */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = B4DB1FADBA2D2C69747AC0D4 /* Build configuration list for PBXNativeTarget "packvideo" */;
|
||||||
|
buildPhases = (
|
||||||
|
9A9086E43BFFE339075FEF01 /* Sources */,
|
||||||
|
507B15D31C90EF8682AFB59C /* Frameworks */,
|
||||||
|
B491C6B43A4AFEBA72EDE202 /* ShellScript */,
|
||||||
|
2E2CA33F02F2C6797FC94387 /* ShellScript */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
BFB0BCC60AAC4EB459F83323 /* PBXBuildRule */,
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = packvideo;
|
||||||
|
productName = packvideo;
|
||||||
|
productReference = 2791201414FE21A0208E5633 /* packvideo */;
|
||||||
|
productType = "com.apple.product-type.tool";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
24E32329DA86341FE2CF714A /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
BuildIndependentTargetsInParallel = YES;
|
||||||
|
};
|
||||||
|
buildConfigurationList = 3F085FB90001EDC1896C0DC9 /* Build configuration list for PBXProject "packvideoxc3osx" */;
|
||||||
|
compatibilityVersion = "Xcode 3.1";
|
||||||
|
hasScannedForEncodings = 1;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
);
|
||||||
|
mainGroup = 945D7BCE010E10DA41ABD532 /* packvideo */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
56EF2BB6F86F47504C45BD06 /* packvideo */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
2E2CA33F02F2C6797FC94387 /* ShellScript */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_NAME}",
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"${CONFIGURATION_BUILD_DIR}/../../../bin/macosx/${FINAL_OUTPUT}",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "if [ \"${CONFIGURATION}\" == \"Release\" ]; then\n${SDKS}/macosx/bin/p4 edit ../bin/macosx/${FINAL_OUTPUT}\n${CP} ${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_NAME} ../bin/macosx/${FINAL_OUTPUT}\nfi\n\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
B491C6B43A4AFEBA72EDE202 /* ShellScript */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_NAME}",
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"${SRCROOT}/bin/${EXECUTABLE_NAME}${IDESUFFIX}${SUFFIX}",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "if [ ! -d ${SRCROOT}/bin ]; then mkdir ${SRCROOT}/bin; fi\n${CP} ${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_NAME} ${SRCROOT}/bin/${EXECUTABLE_NAME}${IDESUFFIX}${SUFFIX}\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
9A9086E43BFFE339075FEF01 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
A9CAC7BF34E647803EDD7969 /* packvideo.cpp in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
10B76258575E95FA8B4FD45A /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 53A745DDC21ECBC748B26AF9 /* burger.toolxcoosx.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
4B999CCB76FCC534EAED986C /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
3F085FB90001EDC1896C0DC9 /* Build configuration list for PBXProject "packvideoxc3osx" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
10B76258575E95FA8B4FD45A /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
B4DB1FADBA2D2C69747AC0D4 /* Build configuration list for PBXNativeTarget "packvideo" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
4B999CCB76FCC534EAED986C /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 24E32329DA86341FE2CF714A /* Project object */;
|
||||||
|
}
|
640
tools/packvideo/source/packvideo.cpp
Normal file
@ -0,0 +1,640 @@
|
|||||||
|
/***************************************
|
||||||
|
|
||||||
|
Tool to pre-process video data for Space Ace IIgs
|
||||||
|
|
||||||
|
Copyright (c) 1995-2015 by Rebecca Ann Heineman <becky@burgerbecky.com>
|
||||||
|
|
||||||
|
It is released under an MIT Open Source license. Please see LICENSE
|
||||||
|
for license details. Yes, you can use it in a
|
||||||
|
commercial title without paying anything, just give me a credit.
|
||||||
|
Please? It's not like I'm asking you for money!
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
#include "packvideo.h"
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Convert the IIgs palette to RGBAWord8_t
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static void BURGER_API ConvertPalette(RGBAWord8_t *pOutput,const Word8 *pInput)
|
||||||
|
{
|
||||||
|
Word uIndex = 0;
|
||||||
|
do {
|
||||||
|
pOutput->m_uRed = Renderer::RGB4ToRGB8Table[pInput[1]&0xFU];
|
||||||
|
pOutput->m_uGreen = Renderer::RGB4ToRGB8Table[pInput[0]>>4U];
|
||||||
|
pOutput->m_uBlue = Renderer::RGB4ToRGB8Table[pInput[0]&0xFU];
|
||||||
|
pOutput->m_uAlpha = 0xFF;
|
||||||
|
pInput+=2;
|
||||||
|
++pOutput;
|
||||||
|
} while (++uIndex<16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Convert the RGBAWord8_t palette to IIgs
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static void BURGER_API ConvertPalette(Word8 *pOutput,const RGBAWord8_t *pInput)
|
||||||
|
{
|
||||||
|
Word uIndex = 0;
|
||||||
|
do {
|
||||||
|
Word uTemp = pInput->m_uGreen&0xF0U;
|
||||||
|
uTemp |= (pInput->m_uBlue>>4U);
|
||||||
|
pOutput[0] = static_cast<Word8>(uTemp);
|
||||||
|
pOutput[1] = static_cast<Word8>(pInput->m_uRed>>4U);
|
||||||
|
++pInput;
|
||||||
|
pOutput+=2;
|
||||||
|
} while (++uIndex<16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Test if the IIgs palette has changed
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static Word BURGER_API ComparePalette(const Word8 *pInput1,const Word8 *pInput2)
|
||||||
|
{
|
||||||
|
return MemoryCompare(pInput1,pInput2,32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Convert bitmap to IIgs format
|
||||||
|
|
||||||
|
8 bits per pixel converted to 4 bits per pixel
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static void BURGER_API ConvertPixelsToIIgs(Word8 *pOutput,const Image *pInput)
|
||||||
|
{
|
||||||
|
WordPtr uStride = pInput->GetStride()-320;
|
||||||
|
const Word8 *pPixels = pInput->GetImage();
|
||||||
|
WordPtr j=200;
|
||||||
|
do {
|
||||||
|
WordPtr i=320/2;
|
||||||
|
do {
|
||||||
|
Word uTemp = pPixels[0]<<4U;
|
||||||
|
uTemp |= (pPixels[1]&0xFU);
|
||||||
|
pOutput[0] = static_cast<Word8>(uTemp);
|
||||||
|
pPixels+=2;
|
||||||
|
++pOutput;
|
||||||
|
} while (--i);
|
||||||
|
pPixels+=uStride;
|
||||||
|
} while (--j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Compress a IIgs keyframe
|
||||||
|
|
||||||
|
The compression only packs runs of a minimum of 3 matching
|
||||||
|
bytes to reduce mode switching during decompression
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static void BURGER_API CompressKeyFrame(OutputMemoryStream *pOutput,const Word8 *pInput)
|
||||||
|
{
|
||||||
|
// Number of bytes to process
|
||||||
|
WordPtr uInputLength = 320*200/2;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// If two bytes or less, just store and exit
|
||||||
|
if (uInputLength<3) {
|
||||||
|
pOutput->Append(static_cast<Word8>(uInputLength));
|
||||||
|
pOutput->Append(pInput,uInputLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for repeater of at LEAST three bytes
|
||||||
|
Word uMatchTest = pInput[0];
|
||||||
|
|
||||||
|
// Is there a run?
|
||||||
|
if ((pInput[1] == uMatchTest) && (pInput[2] == uMatchTest)) {
|
||||||
|
|
||||||
|
// Maximum length of a matched run
|
||||||
|
WordPtr uMaximumRun = 127;
|
||||||
|
if (uInputLength<127) {
|
||||||
|
uMaximumRun = uInputLength; // 1-127
|
||||||
|
}
|
||||||
|
WordPtr uRun = 3-1;
|
||||||
|
while (++uRun<uMaximumRun) {
|
||||||
|
// Find end of repeater
|
||||||
|
if (pInput[uRun]!=uMatchTest) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Encode 128-255 for 0-127 run
|
||||||
|
pOutput->Append(static_cast<Word8>(0x80|uRun));
|
||||||
|
pOutput->Append(static_cast<Word8>(uMatchTest));
|
||||||
|
uInputLength-=uRun;
|
||||||
|
pInput += uRun;
|
||||||
|
} else {
|
||||||
|
// Raw run, minimum size of 2 bytes
|
||||||
|
WordPtr uMaximumRun = 127;
|
||||||
|
if (uInputLength<127) {
|
||||||
|
uMaximumRun = uInputLength;
|
||||||
|
}
|
||||||
|
// Preload the next byte
|
||||||
|
uMatchTest = pInput[1];
|
||||||
|
WordPtr uRun = 2-1;
|
||||||
|
while (++uRun<uMaximumRun) {
|
||||||
|
// Scan for next repeater
|
||||||
|
if (pInput[uRun]==uMatchTest && (pInput[uRun+1]==uMatchTest)) {
|
||||||
|
// Remove from the run
|
||||||
|
--uRun;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Get the next byte
|
||||||
|
uMatchTest = pInput[uRun];
|
||||||
|
}
|
||||||
|
// Perform a raw data transfer
|
||||||
|
// Run 1-128
|
||||||
|
// Encode 0-127
|
||||||
|
pOutput->Append(static_cast<Word8>(uRun));
|
||||||
|
pOutput->Append(pInput,uRun);
|
||||||
|
uInputLength-=uRun;
|
||||||
|
pInput += uRun;
|
||||||
|
}
|
||||||
|
} while (uInputLength);
|
||||||
|
|
||||||
|
// Mark the end of compressed data
|
||||||
|
pOutput->Append(static_cast<Word8>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Compress a IIgs animation frame
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static void BURGER_API CompressAnimFrame(OutputMemoryStream *pOutput,const Word8 *pPreviousFrame,const Word8 *pCurrentFrame)
|
||||||
|
{
|
||||||
|
// Number of bytes to process
|
||||||
|
WordPtr uInputLength = 320*200/2;
|
||||||
|
do {
|
||||||
|
// Check if there were any differences between the frames to create a skip token
|
||||||
|
WordPtr uMaximumRun = 127; // Skip token maximum value
|
||||||
|
if (uInputLength<uMaximumRun) {
|
||||||
|
uMaximumRun = uInputLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test from the previous frame to the current frame
|
||||||
|
WordPtr uRun = 0;
|
||||||
|
do {
|
||||||
|
if (pPreviousFrame[uRun]!=pCurrentFrame[uRun]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (++uRun<uMaximumRun);
|
||||||
|
|
||||||
|
// If the run is at least 2 bytes or end of the data, use it as is
|
||||||
|
|
||||||
|
if ((uRun==uInputLength) || (uRun>=3)) {
|
||||||
|
|
||||||
|
// Output a "skip" data token
|
||||||
|
pOutput->Append(static_cast<Word8>(uRun));
|
||||||
|
pPreviousFrame+=uRun;
|
||||||
|
pCurrentFrame+=uRun;
|
||||||
|
uInputLength-=uRun;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Maximum length of a matched run
|
||||||
|
uMaximumRun = 255;
|
||||||
|
if (uInputLength<255) {
|
||||||
|
uMaximumRun = uInputLength; // 1-255
|
||||||
|
}
|
||||||
|
|
||||||
|
Word uMatchTest = pCurrentFrame[0];
|
||||||
|
uRun = 1;
|
||||||
|
while (uRun<uMaximumRun) {
|
||||||
|
// Find end of repeater
|
||||||
|
if (pCurrentFrame[uRun]!=uMatchTest) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++uRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is there a run of 4 or greater?
|
||||||
|
if (uRun>=4) {
|
||||||
|
// Encode the run length
|
||||||
|
pOutput->Append(static_cast<Word8>(0));
|
||||||
|
pOutput->Append(static_cast<Word8>(uRun));
|
||||||
|
pOutput->Append(static_cast<Word8>(uMatchTest));
|
||||||
|
uInputLength -= uRun;
|
||||||
|
pCurrentFrame += uRun;
|
||||||
|
pPreviousFrame += uRun;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Raw run
|
||||||
|
uMaximumRun = 127;
|
||||||
|
if (uInputLength<127) {
|
||||||
|
uMaximumRun = uInputLength;
|
||||||
|
}
|
||||||
|
uRun = 0;
|
||||||
|
while (++uRun<uMaximumRun) {
|
||||||
|
// Scan for next repeater
|
||||||
|
if (pCurrentFrame[uRun]==uMatchTest && (pCurrentFrame[uRun+1]==uMatchTest) && (pCurrentFrame[uRun+2]==uMatchTest)) {
|
||||||
|
// Remove from the run
|
||||||
|
--uRun;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((pCurrentFrame[uRun]==pPreviousFrame[uRun]) &&
|
||||||
|
(pCurrentFrame[uRun+1]==pPreviousFrame[uRun+1]) &&
|
||||||
|
(pCurrentFrame[uRun+2]==pPreviousFrame[uRun+2])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Get the next byte
|
||||||
|
uMatchTest = pCurrentFrame[uRun];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle some data optimizations
|
||||||
|
|
||||||
|
// If it's only a single byte run and it's the same as the previous
|
||||||
|
// frame? Just skip
|
||||||
|
if ((uRun==1) && (pCurrentFrame[0]==pPreviousFrame[0])) {
|
||||||
|
pOutput->Append(static_cast<Word8>(1));
|
||||||
|
--uInputLength;
|
||||||
|
++pCurrentFrame;
|
||||||
|
++pPreviousFrame;
|
||||||
|
|
||||||
|
// If it's only a single byte run and it's the same as the previous
|
||||||
|
// frame? Just skip
|
||||||
|
} else if ((uRun==2) &&
|
||||||
|
(pCurrentFrame[0]==pPreviousFrame[0]) &&
|
||||||
|
(pCurrentFrame[1]==pPreviousFrame[1])) {
|
||||||
|
pOutput->Append(static_cast<Word8>(2));
|
||||||
|
uInputLength-=2;
|
||||||
|
pCurrentFrame+=2;
|
||||||
|
pPreviousFrame+=2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Perform a raw data transfer
|
||||||
|
// Run 1-128
|
||||||
|
pOutput->Append(static_cast<Word8>(0x80|uRun));
|
||||||
|
pOutput->Append(pCurrentFrame,uRun);
|
||||||
|
uInputLength-=uRun;
|
||||||
|
pCurrentFrame += uRun;
|
||||||
|
pPreviousFrame+=uRun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (uInputLength>=2);
|
||||||
|
|
||||||
|
// Simple check if there's only one byte left
|
||||||
|
|
||||||
|
if (uInputLength==1) {
|
||||||
|
if (pCurrentFrame[0]==pPreviousFrame[0]) {
|
||||||
|
pOutput->Append(static_cast<Word8>(1));
|
||||||
|
} else {
|
||||||
|
pOutput->Append(static_cast<Word8>(0x81));
|
||||||
|
pOutput->Append(pCurrentFrame[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Process a video file into space ace format
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static Word ExtractVideo(OutputMemoryStream *pOutput,const Word8 *pInput,WordPtr uInputLength)
|
||||||
|
{
|
||||||
|
InputMemoryStream InputMem(pInput,uInputLength,TRUE);
|
||||||
|
Image MyImage;
|
||||||
|
FileGIF Giffy;
|
||||||
|
Word8 IIgsPalette[32];
|
||||||
|
Word8 NewIIgsPalette[32];
|
||||||
|
Word uResult = 10;
|
||||||
|
if (!Giffy.Load(&MyImage,&InputMem)) {
|
||||||
|
|
||||||
|
if ((MyImage.GetWidth()!=320) || (MyImage.GetHeight()!=200)) {
|
||||||
|
printf("Input file is not 320 x 200");
|
||||||
|
} else {
|
||||||
|
// Initialize the IIgs palette to invalid values
|
||||||
|
MemoryFill(IIgsPalette,255,sizeof(IIgsPalette));
|
||||||
|
Word8 *pCurrentFrame = static_cast<Word8 *>(Alloc(320*200/2));
|
||||||
|
Word8 *pPreviousFrame = static_cast<Word8 *>(Alloc(320*200/2));
|
||||||
|
int i = 1;
|
||||||
|
do {
|
||||||
|
|
||||||
|
// Process a frame
|
||||||
|
|
||||||
|
// Save space for the chunk size
|
||||||
|
WordPtr uOutputMark = pOutput->GetSize();
|
||||||
|
pOutput->Append(static_cast<Word16>(0));
|
||||||
|
|
||||||
|
// Convert the palette to IIgs format
|
||||||
|
ConvertPalette(NewIIgsPalette,Giffy.GetPalette());
|
||||||
|
|
||||||
|
// Set the default chunk type
|
||||||
|
|
||||||
|
Word8 uTypeFlag = 0x01;
|
||||||
|
|
||||||
|
// Is there a palette update?
|
||||||
|
if (ComparePalette(NewIIgsPalette,IIgsPalette)) {
|
||||||
|
MemoryCopy(IIgsPalette,NewIIgsPalette,sizeof(IIgsPalette));
|
||||||
|
uTypeFlag |= 0x80U;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial frame?
|
||||||
|
if (i==1) {
|
||||||
|
uTypeFlag |= 0x60;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the data type byte
|
||||||
|
pOutput->Append(static_cast<Word8>(uTypeFlag));
|
||||||
|
|
||||||
|
if (uTypeFlag&0x80U) {
|
||||||
|
pOutput->Append(IIgsPalette,32);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvertPixelsToIIgs(pCurrentFrame,&MyImage);
|
||||||
|
|
||||||
|
if (uTypeFlag&0x40) {
|
||||||
|
CompressKeyFrame(pOutput,pCurrentFrame);
|
||||||
|
} else {
|
||||||
|
CompressAnimFrame(pOutput,pPreviousFrame,pCurrentFrame);
|
||||||
|
}
|
||||||
|
MemoryCopy(pPreviousFrame,pCurrentFrame,320*200/2);
|
||||||
|
|
||||||
|
// Update the chunk size
|
||||||
|
Word16 uChuckShort;
|
||||||
|
LittleEndian::Store(&uChuckShort,static_cast<Word16>(pOutput->GetSize()-uOutputMark));
|
||||||
|
pOutput->Overwrite(&uChuckShort,2,uOutputMark);
|
||||||
|
++i;
|
||||||
|
} while (!Giffy.LoadNextFrame(&MyImage,&InputMem));
|
||||||
|
Free(pCurrentFrame);
|
||||||
|
Free(pPreviousFrame);
|
||||||
|
// Append an "End of data" marker
|
||||||
|
pOutput->Append(static_cast<Word16>(0xFF00U));
|
||||||
|
uResult = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Gif input file error!\n");
|
||||||
|
}
|
||||||
|
return uResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Convert a Space Ace file to an animated GIF file
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
static char Name[] = "filexxx.gif";
|
||||||
|
|
||||||
|
static Word EncapsulateToGIF(OutputMemoryStream *pOutput,Filename *pOutputFilename,const Word8 *pInput,WordPtr uInputLength)
|
||||||
|
{
|
||||||
|
// Too small?
|
||||||
|
if (uInputLength<2) {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileGIF GIF;
|
||||||
|
Image MyImage;
|
||||||
|
|
||||||
|
// Create an initial image
|
||||||
|
MyImage.Init(320,200,Image::PIXELTYPE8BIT);
|
||||||
|
MyImage.ClearBitmap();
|
||||||
|
MemoryClear(GIF.GetPalette(),sizeof(GIF.GetPalette()[0])*256);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Decompress a chunk
|
||||||
|
//
|
||||||
|
|
||||||
|
Word uFrame = 0;
|
||||||
|
for (;;) {
|
||||||
|
Word uChunkSize = LittleEndian::LoadAny(reinterpret_cast<const Word16 *>(pInput));
|
||||||
|
if (uChunkSize>=0xFF00) {
|
||||||
|
printf("End of data, frames = %u\n",uFrame);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++uFrame;
|
||||||
|
if (uChunkSize>uInputLength) {
|
||||||
|
printf("Premature end of data\n");
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
if (uChunkSize<2) {
|
||||||
|
printf("Chunk size too small\n");
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
printf("Chunk is %u bytes\n",uChunkSize);
|
||||||
|
const Word8 *pWork = pInput+2;
|
||||||
|
uInputLength -= uChunkSize;
|
||||||
|
pInput+= uChunkSize;
|
||||||
|
uChunkSize-=2;
|
||||||
|
|
||||||
|
// Get the palette token
|
||||||
|
|
||||||
|
if (uChunkSize) {
|
||||||
|
Word uType = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
--uChunkSize;
|
||||||
|
printf("Token = 0x%02X\n",uType);
|
||||||
|
|
||||||
|
if (uType&0x80) {
|
||||||
|
|
||||||
|
// Clear out the palette
|
||||||
|
MemoryClear(GIF.GetPalette(),sizeof(GIF.GetPalette()[0])*256);
|
||||||
|
ConvertPalette(GIF.GetPalette(),pWork);
|
||||||
|
pWork+=32;
|
||||||
|
uChunkSize-=32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Full image or animation frame?
|
||||||
|
if (uType&0x40) {
|
||||||
|
Word uTemp;
|
||||||
|
Word8 *pDest = MyImage.GetImage();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
uTemp = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
if (!uTemp) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (uTemp&0x80) {
|
||||||
|
uTemp&=0x7f;
|
||||||
|
if (uTemp) {
|
||||||
|
// Run length compressed loop
|
||||||
|
Word uSecond = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
Word uFirst = uSecond>>4U;
|
||||||
|
uSecond&=0xF;
|
||||||
|
do {
|
||||||
|
pDest[0] = static_cast<Word8>(uFirst);
|
||||||
|
pDest[1] = static_cast<Word8>(uSecond);
|
||||||
|
pDest+=2;
|
||||||
|
} while (--uTemp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Uncompressed loop
|
||||||
|
do {
|
||||||
|
Word uColor = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
pDest[0] = static_cast<Word8>(uColor>>4U);
|
||||||
|
pDest[1] = static_cast<Word8>(uColor&0xF);
|
||||||
|
pDest+=2;
|
||||||
|
} while (--uTemp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
|
||||||
|
Word uTemp;
|
||||||
|
Word8 *pDest = MyImage.GetImage();
|
||||||
|
Word8 *pEnd = pDest+(320*200);
|
||||||
|
do {
|
||||||
|
uTemp = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
if (!uTemp) {
|
||||||
|
uTemp = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
if (uTemp) {
|
||||||
|
// Run length compressed loop
|
||||||
|
Word uSecond = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
Word uFirst = uSecond>>4U;
|
||||||
|
uSecond&=0xF;
|
||||||
|
do {
|
||||||
|
pDest[0] = static_cast<Word8>(uFirst);
|
||||||
|
pDest[1] = static_cast<Word8>(uSecond);
|
||||||
|
pDest+=2;
|
||||||
|
} while (--uTemp);
|
||||||
|
}
|
||||||
|
} else if (uTemp&0x80) {
|
||||||
|
uTemp&=0x7f;
|
||||||
|
if (uTemp) {
|
||||||
|
// Uncompressed loop
|
||||||
|
do {
|
||||||
|
Word uColor = pWork[0];
|
||||||
|
++pWork;
|
||||||
|
pDest[0] = static_cast<Word8>(uColor>>4U);
|
||||||
|
pDest[1] = static_cast<Word8>(uColor&0xF);
|
||||||
|
pDest+=2;
|
||||||
|
} while (--uTemp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pDest+=(uTemp*2);
|
||||||
|
}
|
||||||
|
} while (pDest<pEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GIF.Save(pOutput,&MyImage);
|
||||||
|
Filename TempName(pOutputFilename[0]);
|
||||||
|
TempName.SetFileExtension(NULL);
|
||||||
|
NumberString Namex(static_cast<Word32>(uFrame),LEADINGZEROS|3);
|
||||||
|
String Name2(TempName.GetPtr());
|
||||||
|
Name2.Remove(Name2.GetLength()-1);
|
||||||
|
Name2.Append(Namex,3);
|
||||||
|
TempName.Set(Name2.GetPtr());
|
||||||
|
TempName.SetFileExtension("gif");
|
||||||
|
printf("Frame %s\n",TempName.GetPtr());
|
||||||
|
pOutput->SaveFile(&TempName);
|
||||||
|
pOutput->Clear();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
|
||||||
|
Main dispatcher
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
int BURGER_ANSIAPI main(int argc,const char **argv)
|
||||||
|
{
|
||||||
|
ConsoleApp MyApp(argc,argv);
|
||||||
|
CommandParameterBooleanTrue DoVideo("Process Video","v");
|
||||||
|
CommandParameterBooleanTrue ConvertToGIF("Convert to GIF","g");
|
||||||
|
const CommandParameter *MyParms[] = {
|
||||||
|
&DoVideo,
|
||||||
|
&ConvertToGIF
|
||||||
|
};
|
||||||
|
#if 0
|
||||||
|
Filename DeathName;
|
||||||
|
DeathName.SetFromNative("D:\\projects\\burger\\games\\spaceace\\iigs\\assets\\death\\death07.gif");
|
||||||
|
FileGIF Giffy;
|
||||||
|
InputMemoryStream InputMem;
|
||||||
|
if (!InputMem.Open(&DeathName)) {
|
||||||
|
Image MyImage;
|
||||||
|
if (!Giffy.Load(&MyImage,&InputMem)) {
|
||||||
|
OutputMemoryStream OutputMem;
|
||||||
|
int i = 1;
|
||||||
|
do {
|
||||||
|
OutputMem.Clear();
|
||||||
|
Giffy.Save(&OutputMem,&MyImage);
|
||||||
|
char name[256];
|
||||||
|
sprintf(name,"D:\\projects\\burger\\games\\spaceace\\iigs\\assets\\death\\death07x%d.gif",i);
|
||||||
|
DeathName.SetFromNative(name);
|
||||||
|
OutputMem.SaveFile(&DeathName);
|
||||||
|
++i;
|
||||||
|
} while (!Giffy.LoadNextFrame(&MyImage,&InputMem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
argc = MyApp.GetArgc();
|
||||||
|
argv = MyApp.GetArgv();
|
||||||
|
argc = CommandParameter::Process(argc,argv,MyParms,sizeof(MyParms)/sizeof(MyParms[0]),
|
||||||
|
"Usage: packvideo InputFile OutputFile\n\n"
|
||||||
|
"Preprocess video data for Space Ace IIgs.\nCopyright by Rebecca Ann Heineman\n",3);
|
||||||
|
if (argc<0) {
|
||||||
|
Globals::SetErrorCode(10);
|
||||||
|
} else {
|
||||||
|
MyApp.SetArgc(argc);
|
||||||
|
|
||||||
|
Filename InputName;
|
||||||
|
InputName.SetFromNative(argv[1]);
|
||||||
|
|
||||||
|
WordPtr uInputLength;
|
||||||
|
Word8 *pInput = static_cast<Word8 *>(FileManager::LoadFile(&InputName,&uInputLength));
|
||||||
|
if (!pInput) {
|
||||||
|
printf("Can't open %s!\n",argv[1]);
|
||||||
|
Globals::SetErrorCode(10);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Convert gif to data
|
||||||
|
if (DoVideo.GetValue()) {
|
||||||
|
OutputMemoryStream Output;
|
||||||
|
if (ExtractVideo(&Output,pInput,uInputLength)) {
|
||||||
|
printf("Can't convert %s!\n",argv[1]);
|
||||||
|
Globals::SetErrorCode(10);
|
||||||
|
} else {
|
||||||
|
Filename OutputName;
|
||||||
|
OutputName.SetFromNative(argv[2]);
|
||||||
|
if (Output.SaveFile(&OutputName)) {
|
||||||
|
printf("Can't save %s!\n",argv[2]);
|
||||||
|
Globals::SetErrorCode(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert raw video to GIF
|
||||||
|
} else if (ConvertToGIF.GetValue()) {
|
||||||
|
Filename OutputName;
|
||||||
|
OutputName.SetFromNative(argv[2]);
|
||||||
|
OutputMemoryStream Output;
|
||||||
|
if (EncapsulateToGIF(&Output,&OutputName,pInput,uInputLength)) {
|
||||||
|
printf("Can't convert %s!\n",argv[1]);
|
||||||
|
Globals::SetErrorCode(10);
|
||||||
|
} else {
|
||||||
|
// if (Output.SaveFile(&OutputName)) {
|
||||||
|
// printf("Can't save %s!\n",argv[2]);
|
||||||
|
// Globals::SetErrorCode(10);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("No conversion selected for %s!\n",argv[1]);
|
||||||
|
Globals::SetErrorCode(10);
|
||||||
|
}
|
||||||
|
Free(pInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Globals::GetErrorCode();
|
||||||
|
}
|
23
tools/packvideo/source/packvideo.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/***************************************
|
||||||
|
|
||||||
|
Tool to pre-process video data for Space Ace IIgs
|
||||||
|
|
||||||
|
Copyright (c) 1995-2015 by Rebecca Ann Heineman <becky@burgerbecky.com>
|
||||||
|
|
||||||
|
It is released under an MIT Open Source license. Please see LICENSE
|
||||||
|
for license details. Yes, you can use it in a
|
||||||
|
commercial title without paying anything, just give me a credit.
|
||||||
|
Please? It's not like I'm asking you for money!
|
||||||
|
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
#ifndef __PACKVIDEO_H__
|
||||||
|
#define __PACKVIDEO_H__
|
||||||
|
|
||||||
|
#ifndef __BURGER__
|
||||||
|
#include <burger.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int BURGER_ANSIAPI main(int argc,const char **argv);
|
||||||
|
|
||||||
|
#endif
|