├── .gitignore ├── Core ├── ByteArray │ ├── ByteArrayExporter.cs │ ├── ByteArrayHexEditor.cs │ └── ByteArrayImporter.cs ├── Command │ ├── Command.cs │ ├── ICommandHost.cs │ └── IWorkspaceHost.cs ├── Controller │ ├── Controller.cs │ ├── List │ │ ├── SubcontrollerListGroup.cs │ │ └── SubresourceListAttribute.cs │ ├── Slot │ │ ├── SubcontrollerSlotGroup.cs │ │ └── SubresourceSlotAttribute.cs │ ├── SubcontrollerGroup.cs │ └── SubresourceAttribute.cs ├── DeleteVerb.cs ├── Editor.cs ├── Embeds.cs ├── Export │ ├── ExportVerb.cs │ └── Exporter.cs ├── Gui │ ├── ChoiceDialog.cs │ ├── HexView.cs │ ├── MainControl.cs │ ├── MainForm.cs │ ├── ResourceBox.cs │ ├── ResourcePanel.cs │ ├── ResourceTreeView.cs │ ├── ToolStripCommandButton.cs │ ├── ToolStripCommandMenuItem.cs │ ├── UndockCommand.cs │ └── VerbContextMenuStrip.cs ├── IResource.cs ├── IUserInterface.cs ├── Import │ ├── ImportAddVerb.cs │ ├── ImportReplaceVerb.cs │ └── Importer.cs ├── Legacy │ ├── LegacyController.cs │ ├── LegacyEditor.cs │ ├── LegacyEditorControlWrapper.cs │ ├── LegacyMoveVerb.cs │ ├── LegacyVerb.cs │ └── OrphanLegacyControllerAttribute.cs ├── Registrar.cs ├── Search │ ├── FindFirstCommand.cs │ ├── FindLastCommand.cs │ ├── FindNextCommand.cs │ └── FindPreviousCommand.cs ├── UserChoice.cs ├── Verb │ ├── DirectVerb.cs │ ├── GroupVerb.cs │ ├── IVerbExecutor.cs │ ├── TransitiveVerb.cs │ └── Verb.cs ├── Walker.cs └── Workspace.cs ├── Crash.UI ├── Crash.UI.csproj ├── Forms │ ├── GameVersionForm.Designer.cs │ ├── GameVersionForm.cs │ └── GameVersionForm.resx └── Properties │ ├── Resources.Designer.cs │ ├── Resources.ja.Designer.cs │ ├── Resources.ja.resx │ └── Resources.resx ├── Crash ├── Configuration System │ └── GameVersion.cs ├── Editors │ └── UnprocessedChunkHexEditor.cs ├── Error System │ ├── EntryAddException.cs │ ├── ErrorManager.cs │ ├── ErrorResponse.cs │ ├── ErrorSignalEventArgs.cs │ ├── ErrorSignalEventHandler.cs │ ├── LoadAbortedException.cs │ ├── LoadSkippedException.cs │ └── PackingException.cs ├── Formats │ ├── Common Formats │ │ └── RIFF │ │ │ ├── RIFF.cs │ │ │ ├── RIFFData.cs │ │ │ └── RIFFItem.cs │ ├── Crash Formats │ │ ├── Animation │ │ │ ├── AnimationEntry.cs │ │ │ ├── AnimationEntryLoader.cs │ │ │ ├── ColoredAnimationEntry.cs │ │ │ ├── ColoredAnimationEntryLoader.cs │ │ │ ├── Frame.cs │ │ │ ├── FrameCollision.cs │ │ │ ├── FrameVertex.cs │ │ │ ├── OldAnimationEntry.cs │ │ │ ├── OldAnimationEntryLoader.cs │ │ │ ├── OldFrame.cs │ │ │ ├── OldFrameVertex.cs │ │ │ ├── ProtoAnimationEntry.cs │ │ │ └── ProtoAnimationEntryLoader.cs │ │ ├── Base │ │ │ ├── Chunk │ │ │ │ ├── Chunk.cs │ │ │ │ ├── ChunkExporter.cs │ │ │ │ ├── ChunkLoader.cs │ │ │ │ ├── ChunkTypeAttribute.cs │ │ │ │ └── UnprocessedChunk.cs │ │ │ ├── Entry Chunk │ │ │ │ ├── EntryChunk.cs │ │ │ │ └── EntryChunkLoader.cs │ │ │ └── Entry │ │ │ │ ├── ENameComparer.cs │ │ │ │ ├── Entry.cs │ │ │ │ ├── EntryExporter.cs │ │ │ │ ├── EntryLoader.cs │ │ │ │ ├── EntryTypeAttribute.cs │ │ │ │ ├── IEntry.cs │ │ │ │ └── UnprocessedEntry.cs │ │ ├── Demo │ │ │ ├── DemoEntry.cs │ │ │ └── DemoEntryLoader.cs │ │ ├── GOOL │ │ │ ├── Frame Groups │ │ │ │ ├── FontGroup.cs │ │ │ │ ├── FontGroup2.cs │ │ │ │ ├── FontTexture.cs │ │ │ │ ├── FontTexture2.cs │ │ │ │ ├── ImageGroup.cs │ │ │ │ ├── ImageGroup2.cs │ │ │ │ ├── ImageTexture.cs │ │ │ │ ├── ImageTexture2.cs │ │ │ │ ├── ProtoSpriteTexture.cs │ │ │ │ ├── SpriteGroup.cs │ │ │ │ ├── SpriteGroup2.cs │ │ │ │ ├── SpriteTexture.cs │ │ │ │ ├── SpriteTexture2.cs │ │ │ │ ├── TextGroup.cs │ │ │ │ ├── VertexGroup.cs │ │ │ │ ├── VertexGroup2.cs │ │ │ │ └── VertexGroup3.cs │ │ │ ├── GOOLArgument.cs │ │ │ ├── GOOLEntry.cs │ │ │ ├── GOOLEntryLoader.cs │ │ │ ├── GOOLFrameGroup.cs │ │ │ ├── GOOLFrameGroupBase.cs │ │ │ ├── GOOLFrameGroupWithChunk.cs │ │ │ ├── GOOLInstruction.cs │ │ │ ├── GOOLInstructionAttribute.cs │ │ │ ├── GOOLInstructionList.cs │ │ │ ├── GOOLInterpreter.cs │ │ │ ├── GOOLStateDescriptor.cs │ │ │ ├── GOOLUnknownInstruction.cs │ │ │ └── MIPSInstruction.cs │ │ ├── Image │ │ │ ├── ImageEntry.cs │ │ │ └── ImageEntryLoader.cs │ │ ├── Map │ │ │ ├── MapEntry.cs │ │ │ └── MapEntryLoader.cs │ │ ├── Model │ │ │ ├── ModelEntry.cs │ │ │ ├── ModelEntryLoader.cs │ │ │ ├── ModelExtendedTexture.cs │ │ │ ├── ModelPosition.cs │ │ │ ├── ModelStruct.cs │ │ │ ├── ModelTexture.cs │ │ │ ├── ModelTransformedTriangle.cs │ │ │ ├── OldModelEntry.cs │ │ │ ├── OldModelEntryLoader.cs │ │ │ ├── OldModelPolygon.cs │ │ │ ├── OldModelStruct.cs │ │ │ └── OldModelTexture.cs │ │ ├── Music │ │ │ ├── MusicEntry.cs │ │ │ ├── MusicEntryLoader.cs │ │ │ ├── OldMusicEntry.cs │ │ │ └── OldMusicEntryLoader.cs │ │ ├── Mystery │ │ │ ├── MysteryMultiItemEntry.cs │ │ │ └── MysteryUniItemEntry.cs │ │ ├── NSD │ │ │ ├── NSD.cs │ │ │ ├── NSDLink.cs │ │ │ ├── NSDSpawnPoint.cs │ │ │ ├── OldNSD.cs │ │ │ └── ProtoNSD.cs │ │ ├── NSF.cs │ │ ├── Normal │ │ │ ├── NormalChunk.cs │ │ │ └── NormalChunkLoader.cs │ │ ├── Palette │ │ │ ├── PaletteEntry.cs │ │ │ └── PaletteEntryLoader.cs │ │ ├── SLST │ │ │ ├── OldSLSTDelta.cs │ │ │ ├── OldSLSTEntry.cs │ │ │ ├── OldSLSTEntryLoader.cs │ │ │ ├── OldSLSTPolygonID.cs │ │ │ ├── OldSLSTSource.cs │ │ │ ├── SLSTDelta.cs │ │ │ ├── SLSTEntry.cs │ │ │ ├── SLSTEntryLoader.cs │ │ │ ├── SLSTPolygonID.cs │ │ │ └── SLSTSource.cs │ │ ├── Scenery │ │ │ ├── OldSceneryColor.cs │ │ │ ├── OldSceneryEntry.cs │ │ │ ├── OldSceneryEntryLoader.cs │ │ │ ├── OldSceneryPolygon.cs │ │ │ ├── OldSceneryTexture.cs │ │ │ ├── OldSceneryVertex.cs │ │ │ ├── ProtoSceneryEntry.cs │ │ │ ├── ProtoSceneryEntryLoader.cs │ │ │ ├── ProtoSceneryPolygon.cs │ │ │ ├── ProtoSceneryVertex.cs │ │ │ ├── SceneryColor.cs │ │ │ ├── SceneryEntry.cs │ │ │ ├── SceneryEntryLoader.cs │ │ │ ├── SceneryQuad.cs │ │ │ ├── SceneryTriangle.cs │ │ │ └── SceneryVertex.cs │ │ ├── Sound │ │ │ ├── OldSoundChunk.cs │ │ │ ├── OldSoundChunkLoader.cs │ │ │ ├── SoundChunk.cs │ │ │ ├── SoundChunkLoader.cs │ │ │ ├── SoundEntry.cs │ │ │ └── SoundEntryLoader.cs │ │ ├── Speech │ │ │ ├── SpeechChunk.cs │ │ │ ├── SpeechChunkLoader.cs │ │ │ ├── SpeechEntry.cs │ │ │ └── SpeechEntryLoader.cs │ │ ├── T15 │ │ │ ├── T15Entry.cs │ │ │ └── T15EntryLoader.cs │ │ ├── T17 │ │ │ ├── T17Entry.cs │ │ │ └── T17EntryLoader.cs │ │ ├── T21 │ │ │ ├── T21Entry.cs │ │ │ └── T21EntryLoader.cs │ │ ├── T6 │ │ │ ├── T6Entry.cs │ │ │ └── T6EntryLoader.cs │ │ ├── Texture │ │ │ ├── TextureChunk.cs │ │ │ └── TextureChunkLoader.cs │ │ ├── Wavebank │ │ │ ├── WavebankChunk.cs │ │ │ ├── WavebankChunkLoader.cs │ │ │ ├── WavebankEntry.cs │ │ │ └── WavebankEntryLoader.cs │ │ └── Zone │ │ │ ├── Entity.cs │ │ │ ├── EntityBasicProperty.cs │ │ │ ├── EntityBasicPropertyLoader.cs │ │ │ ├── EntityID.cs │ │ │ ├── EntityInt32Property.cs │ │ │ ├── EntityInt32PropertyLoader.cs │ │ │ ├── EntityPosition.cs │ │ │ ├── EntityPositionProperty.cs │ │ │ ├── EntityPositionPropertyLoader.cs │ │ │ ├── EntityProperty.cs │ │ │ ├── EntityPropertyLoader.cs │ │ │ ├── EntityPropertyRow.cs │ │ │ ├── EntityPropertyTypeAttribute.cs │ │ │ ├── EntitySetting.cs │ │ │ ├── EntitySettingProperty.cs │ │ │ ├── EntitySettingPropertyLoader.cs │ │ │ ├── EntityT4Property.cs │ │ │ ├── EntityT4PropertyLoader.cs │ │ │ ├── EntityUInt32Property.cs │ │ │ ├── EntityUInt32PropertyLoader.cs │ │ │ ├── EntityUInt8Property.cs │ │ │ ├── EntityUInt8PropertyLoader.cs │ │ │ ├── EntityUnknownProperty.cs │ │ │ ├── EntityVictim.cs │ │ │ ├── EntityVictimProperty.cs │ │ │ ├── EntityVictimPropertyLoader.cs │ │ │ ├── OldCamera.cs │ │ │ ├── OldCameraNeighbor.cs │ │ │ ├── OldCameraPosition.cs │ │ │ ├── OldEntity.cs │ │ │ ├── OldZoneEntry.cs │ │ │ ├── OldZoneEntryLoader.cs │ │ │ ├── ProtoEntity.cs │ │ │ ├── ProtoEntityPosition.cs │ │ │ ├── ProtoZoneEntry.cs │ │ │ ├── ProtoZoneEntryLoader.cs │ │ │ ├── ZoneEntry.cs │ │ │ └── ZoneEntryLoader.cs │ └── PSX Formats │ │ ├── ADPCM │ │ ├── SampleLine.cs │ │ ├── SampleLineFlags.cs │ │ └── SampleSet.cs │ │ ├── SEP.cs │ │ ├── SEQ.cs │ │ ├── SeqExporter.cs │ │ ├── SeqImporter.cs │ │ ├── SeqToMidiExporter.cs │ │ └── VAB │ │ ├── VAB.cs │ │ ├── VH.cs │ │ ├── VHProgram.cs │ │ ├── VHTone.cs │ │ ├── VhExporter.cs │ │ └── VhImporter.cs ├── LevelWorkspace.cs ├── Utility │ ├── ADPCMConv.cs │ ├── Aligner.cs │ ├── AutoBitConv.cs │ ├── BEBitConv.cs │ ├── BitConv.cs │ ├── Endianness.cs │ ├── IPosition.cs │ ├── ListExt.cs │ ├── MIDIConv.cs │ ├── NumberExt.cs │ ├── PixelConv.cs │ ├── Position.cs │ ├── StringExt.cs │ └── WaveConv.cs └── Verb │ └── DeleteEntityVerb.cs ├── CrashEdit.Main.csproj ├── CrashEdit.sln ├── CrashEdit ├── App.config ├── ConfigEditor.Designer.cs ├── ConfigEditor.cs ├── ConfigEditor.resx ├── Controllers │ ├── Animation │ │ ├── AnimationEntryController.cs │ │ ├── ColoredAnimationEntryController.cs │ │ ├── FrameController.cs │ │ ├── OldAnimationEntryController.cs │ │ └── OldFrameController.cs │ ├── Base │ │ ├── Chunk │ │ │ └── ChunkController.cs │ │ ├── Entry Chunk │ │ │ └── EntryChunkController.cs │ │ └── Entry │ │ │ └── EntryController.cs │ ├── Controller.cs │ ├── ControllerMenuDelegate.cs │ ├── GOOL │ │ └── GOOLEntryController.cs │ ├── Map │ │ └── MapEntryController.cs │ ├── Model │ │ ├── ModelEntryController.cs │ │ └── OldModelEntryController.cs │ ├── Music │ │ ├── MusicEntryController.cs │ │ └── OldMusicEntryController.cs │ ├── Mystery │ │ └── MysteryUniItemEntryController.cs │ ├── NSFController.cs │ ├── Palette │ │ └── PaletteEntryController.cs │ ├── SLST │ │ ├── OldSLSTDeltaController.cs │ │ ├── OldSLSTSourceController.cs │ │ ├── SLSTDeltaController.cs │ │ └── SLSTSourceController.cs │ ├── Scenery │ │ ├── OldSceneryEntryController.cs │ │ ├── ProtoSceneryEntryController.cs │ │ └── SceneryEntryController.cs │ ├── Sound │ │ └── SoundEntryController.cs │ ├── Speech │ │ └── SpeechEntryController.cs │ ├── Texture │ │ └── TextureChunkController.cs │ ├── Unprocessed │ │ ├── UnprocessedChunkController.cs │ │ └── UnprocessedEntryController.cs │ └── Zone │ │ ├── EntityController.cs │ │ ├── OldCameraController.cs │ │ ├── OldEntityController.cs │ │ ├── OldZoneEntryController.cs │ │ ├── ProtoEntityController.cs │ │ ├── ProtoZoneEntryController.cs │ │ └── ZoneEntryController.cs ├── Controls │ ├── 3D │ │ ├── AnimationEntryViewer.cs │ │ ├── BaseAnimationEntryViewer.cs │ │ ├── BaseSceneryEntryViewer.cs │ │ ├── ControlsKeyboardInfo.cs │ │ ├── GLViewer.cs │ │ ├── GLViewerLoader.cs │ │ ├── OctreeRenderer.cs │ │ ├── OldAnimationEntryViewer.cs │ │ ├── OldSceneryEntryViewer.cs │ │ ├── OldZoneEntryViewer.cs │ │ ├── ProtoSceneryEntryViewer.cs │ │ ├── ProtoZoneEntryViewer.cs │ │ ├── SceneryEntryViewer.cs │ │ └── ZoneEntryViewer.cs │ ├── EntityBox.Designer.cs │ ├── EntityBox.cs │ ├── EntityBox.resx │ ├── EntryChunkBox.cs │ ├── EntryChunkBox.resx │ ├── GOOLBox.cs │ ├── GetAllControls.cs │ ├── MapEntryViewer.cs │ ├── MysteryBox.cs │ ├── NSFBox.cs │ ├── OldCameraBox.Designer.cs │ ├── OldCameraBox.cs │ ├── OldCameraBox.resx │ ├── OldEntityBox.Designer.cs │ ├── OldEntityBox.cs │ ├── OldEntityBox.resx │ ├── OldFrameBox.Designer.cs │ ├── OldFrameBox.cs │ ├── OldFrameBox.resx │ ├── OldSLSTDeltaBox.cs │ ├── OldSLSTSourceBox.cs │ ├── PaletteEntryBox.cs │ ├── ProtoEntityBox.Designer.cs │ ├── ProtoEntityBox.cs │ ├── ProtoEntityBox.resx │ ├── SLSTDeltaBox.cs │ ├── SLSTSourceBox.cs │ ├── SoundBox.cs │ ├── SoundBox.resx │ └── TextureChunkBox.cs ├── CrashEdit.csproj ├── ExternalTool.cs ├── FileFilters.cs ├── FileUtil.cs ├── Forms │ ├── ErrorReporter.Designer.cs │ ├── ErrorReporter.cs │ ├── ErrorReporter.resx │ ├── InputWindow.Designer.cs │ ├── InputWindow.cs │ ├── InputWindow.resx │ ├── InterpolatorForm.Designer.cs │ ├── InterpolatorForm.cs │ ├── InterpolatorForm.resx │ ├── NewEntryForm.Designer.cs │ ├── NewEntryForm.cs │ ├── NewEntryForm.resx │ ├── ProgressBarForm.Designer.cs │ ├── ProgressBarForm.cs │ ├── ProgressBarForm.resx │ ├── TextureViewer.Designer.cs │ ├── TextureViewer.cs │ └── TextureViewer.resx ├── GUIException.cs ├── HexBox.cs ├── OldMainForm.cs ├── OldMainForm.resx ├── OldResources.cs ├── OldResources.resx ├── Program.cs ├── Properties │ ├── Resources.Designer.cs │ ├── Resources.ja.resx │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Render │ ├── FontTable.cs │ ├── ProjectionInfo.cs │ ├── RenderInfo.cs │ ├── Shader.cs │ ├── ShaderFuncs.cs │ ├── Shaders │ │ ├── crash1-generic.frag │ │ ├── crash1-generic.vert │ │ ├── default4.frag │ │ ├── generic.vert │ │ ├── line-static.vert │ │ ├── octree.frag │ │ ├── octree.vert │ │ ├── screen.frag │ │ ├── screen.vert │ │ ├── sprite-generic.vert │ │ └── sprite.frag │ ├── VAO.cs │ ├── VBO.cs │ └── Vertex.cs ├── Resources │ ├── Icons │ │ ├── NSD.ico │ │ ├── NSF.ico │ │ └── cbhacks-logo-new.ico │ └── Textures │ │ ├── ActivatorBox.png │ │ ├── Apple.png │ │ ├── AppleBox.png │ │ ├── ArrowBox.png │ │ ├── BodyslamBox.png │ │ ├── Box.png │ │ ├── Checkpoint.png │ │ ├── DetonatorBox.png │ │ ├── DetonatorBoxTop.png │ │ ├── IronArrowBox.png │ │ ├── IronBox.png │ │ ├── Life.png │ │ ├── LifeBox.png │ │ ├── Mask.png │ │ ├── MaskBox.png │ │ ├── Nitro.png │ │ ├── NitroTop.png │ │ ├── Point.png │ │ ├── QuestionMarkBox.png │ │ ├── TNT.png │ │ ├── TNTTop.png │ │ ├── Time1BoxTexture.png │ │ ├── Time2BoxTexture.png │ │ ├── Time3BoxTexture.png │ │ ├── TimeBoxTopTexture.png │ │ ├── UnknownBox.png │ │ ├── UnknownBoxTop.png │ │ └── UnknownPickup.png ├── Utils │ ├── ArrayRef.cs │ ├── GameScales.cs │ ├── MathExt.cs │ ├── OpenTK Integration │ │ ├── AnimationRenderer.cs │ │ ├── EntityVisual.cs │ │ ├── EntityVisualList.cs │ │ ├── OldAnimationRenderer.cs │ │ └── TexturePageList.cs │ ├── ResourceLoad.cs │ └── StopwatchExt.cs ├── freetype6-win32.dll └── freetype6-win64.dll ├── CrashHacks ├── CrashHacks.csproj ├── Main.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Properties │ ├── Resources.Designer.cs │ └── Resources.resx ├── Resources │ ├── input-gaming-3.png │ └── media-optical-5.png ├── Script.cs ├── Scripts │ ├── Animation │ │ ├── ReverseScript.cs │ │ └── ShuffleScript.cs │ ├── Other │ │ ├── ScaleLevelScript.cs │ │ └── SingleAnimationScript.cs │ ├── Scenery │ │ ├── Color │ │ │ ├── BaseScript.cs │ │ │ ├── GrayscaleScript.cs │ │ │ ├── NoBlueScript.cs │ │ │ ├── NoGreenScript.cs │ │ │ ├── NoRedScript.cs │ │ │ ├── RandomScript.cs │ │ │ └── SwizzlePerMapScript.cs │ │ ├── FXScript.cs │ │ ├── FeastScript.cs │ │ ├── NoTexScript.cs │ │ └── ScrumpScript.cs │ └── Zone │ │ ├── CloseCameraScript.cs │ │ ├── DistanceFogScript.cs │ │ ├── DistanceFogScript2.cs │ │ ├── DistanceUnfogScript.cs │ │ ├── EasyRelicsScript.cs │ │ ├── GlobalBonusScript.cs │ │ ├── GlobalTestScript.cs │ │ ├── JumpyRacersScript.cs │ │ ├── No298Script.cs │ │ ├── NoDarknessScript.cs │ │ ├── NoWarpBarriersScript.cs │ │ ├── WalkOnCookerScript.cs │ │ ├── WalkOnWaterScript.cs │ │ ├── WaterFXScript.cs │ │ └── ZoneCollisionFuckeryScript.cs ├── SupportLevel.cs ├── app.config └── packages.config ├── Embeds └── Images │ ├── Anchor.gif │ ├── Arrow.gif │ ├── Erase.gif │ ├── File.gif │ ├── Fire.png │ ├── Floppy.gif │ ├── Folder.gif │ ├── FolderOpen.gif │ ├── JournalBlue.gif │ ├── JournalCode.gif │ ├── JournalCyan.gif │ ├── JournalOrange.gif │ ├── JournalRed.gif │ ├── JournalWhite.gif │ ├── MagnifyingGlass.gif │ ├── MusicNoteBlue.gif │ ├── MusicNoteRed.gif │ ├── MusicNoteYellow.gif │ ├── Painting.gif │ ├── README.md │ ├── RecordFirst.gif │ ├── RecordLast.gif │ ├── RecordNext.gif │ ├── RecordPrevious.gif │ ├── Sitemap.png │ ├── SpeakerBlue.gif │ ├── SpeakerWhite.gif │ ├── ThingBlue.gif │ ├── ThingCode.gif │ ├── ThingCrimson.gif │ ├── ThingGray.gif │ ├── ThingLime.gif │ ├── ThingOrange.gif │ ├── ThingRed.gif │ ├── ThingViolet.gif │ └── ThingYellow.gif ├── FTBitmapExtensions ├── FTBitmapExtensions.cs └── FTBitmapExtensions.csproj ├── ISO2PSX ├── ISO2PSX.cs └── ISO2PSX.csproj ├── LICENSE.md ├── README-CE2.md ├── README.md └── appveyor.yml /.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | *.suo 3 | *.user 4 | bin 5 | obj 6 | .vs 7 | packages/* 8 | .idea/* -------------------------------------------------------------------------------- /Core/ByteArray/ByteArrayExporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class ByteArrayExporter : Exporter 5 | { 6 | 7 | public override string Text => "Raw data"; 8 | 9 | public override bool Export(IUserInterface ui, out ReadOnlySpan buf, byte[] res) 10 | { 11 | ArgumentNullException.ThrowIfNull(ui); 12 | ArgumentNullException.ThrowIfNull(res); 13 | 14 | buf = new ReadOnlySpan(res); 15 | return true; 16 | } 17 | 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Core/ByteArray/ByteArrayHexEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace CrashEdit 4 | { 5 | 6 | public sealed class ByteArrayHexEditor : Editor 7 | { 8 | 9 | public override string Text => "Hex"; 10 | 11 | public override bool ApplicableForSubject(Controller subj) 12 | { 13 | ArgumentNullException.ThrowIfNull(subj); 14 | 15 | return subj.Resource is byte[]; 16 | } 17 | 18 | protected override Control MakeControl() 19 | { 20 | return new HexView 21 | { 22 | Data = (byte[])Subject.Resource, 23 | DataChangeHandler = HexView_DataChangeHandler, 24 | }; 25 | } 26 | 27 | private bool HexView_DataChangeHandler(int destOffset, int destLength, byte[] source) 28 | { 29 | var data = (byte[])Subject.Resource; 30 | 31 | if (destLength != source.Length) 32 | throw new ArgumentException(); 33 | if (destOffset < 0 || destOffset >= data.Length) 34 | throw new ArgumentException(); 35 | 36 | Array.Copy(source, 0, data, destOffset, destLength); 37 | return true; 38 | } 39 | 40 | public override void Sync() 41 | { 42 | ((HexView)Control).Invalidate(); 43 | } 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /Core/ByteArray/ByteArrayImporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class ByteArrayImporter : Importer 5 | { 6 | 7 | public override bool Import(IUserInterface ui, ReadOnlySpan buf, out byte[] res) 8 | { 9 | ArgumentNullException.ThrowIfNull(ui); 10 | 11 | res = buf.ToArray(); 12 | return true; 13 | } 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Core/Command/Command.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class Command 5 | { 6 | 7 | public Command(ICommandHost host) 8 | { 9 | ArgumentNullException.ThrowIfNull(host); 10 | 11 | Host = host; 12 | } 13 | 14 | public ICommandHost Host { get; } 15 | 16 | public IWorkspaceHost? WsHost => Host.ActiveWorkspaceHost; 17 | 18 | public virtual string Text => GetType().Name; 19 | 20 | public virtual string ImageKey => ""; 21 | 22 | public virtual bool Ready => true; 23 | 24 | public abstract bool Execute(); 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Core/Command/ICommandHost.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public interface ICommandHost : IUserInterface 5 | { 6 | 7 | IWorkspaceHost? ActiveWorkspaceHost { get; } 8 | 9 | public event EventHandler? ResyncSuggested; 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Core/Command/IWorkspaceHost.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public interface IWorkspaceHost 5 | { 6 | 7 | Controller RootController { get; } 8 | 9 | Controller? ActiveController { get; set; } 10 | 11 | Predicate? SearchPredicate { get; } 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Core/Controller/List/SubresourceListAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace CrashEdit 4 | { 5 | 6 | [AttributeUsage(AttributeTargets.Property)] 7 | public sealed class SubresourceListAttribute : SubresourceAttribute 8 | { 9 | 10 | public SubresourceListAttribute([CallerLineNumber] int order = 0) 11 | { 12 | Order = order; 13 | } 14 | 15 | public int Order { get; } 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Core/Controller/Slot/SubresourceSlotAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace CrashEdit 4 | { 5 | 6 | [AttributeUsage(AttributeTargets.Property)] 7 | public sealed class SubresourceSlotAttribute : SubresourceAttribute 8 | { 9 | 10 | public SubresourceSlotAttribute([CallerLineNumber] int order = 0) 11 | { 12 | Order = order; 13 | } 14 | 15 | public int Order { get; } 16 | 17 | public bool AllowNull { get; set; } 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Core/Controller/SubcontrollerGroup.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class SubcontrollerGroup 5 | { 6 | 7 | public SubcontrollerGroup(Controller owner) 8 | { 9 | ArgumentNullException.ThrowIfNull(owner); 10 | 11 | Owner = owner; 12 | } 13 | 14 | public Controller Owner { get; } 15 | 16 | public List Members { get; } = 17 | new List(); 18 | 19 | public abstract int Order { get; } 20 | 21 | public abstract string Text { get; } 22 | 23 | public abstract Type ResourceType { get; } 24 | 25 | public virtual bool CanAdd => false; 26 | 27 | public virtual void Add(object res) => throw new NotImplementedException(); 28 | 29 | public virtual bool CanRemove => false; 30 | 31 | public virtual void Remove(Controller subctlr) => throw new NotImplementedException(); 32 | 33 | public virtual bool CanReplace => false; 34 | 35 | public virtual void Replace(Controller subctlr, object newRes) => throw new NotImplementedException(); 36 | 37 | public abstract void Sync(); 38 | 39 | public abstract string MakeTextForMember(Controller ctlr); 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Core/Controller/SubresourceAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class SubresourceAttribute : Attribute { } 5 | 6 | } 7 | -------------------------------------------------------------------------------- /Core/DeleteVerb.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | public class DeleteVerb : DirectVerb 4 | { 5 | public override string Text => "Delete"; 6 | 7 | public override string ImageKey => "Erase"; 8 | 9 | public override bool ApplicableForSubject(Controller subj) 10 | { 11 | ArgumentNullException.ThrowIfNull(subj); 12 | 13 | return subj.ParentGroup?.CanRemove ?? false; 14 | } 15 | 16 | public override void Execute(IUserInterface ui) 17 | { 18 | ArgumentNullException.ThrowIfNull(ui); 19 | if (Subject == null) 20 | throw new InvalidOperationException(); 21 | if (Subject.ParentGroup == null) 22 | throw new InvalidOperationException(); 23 | 24 | Subject.ParentGroup.Remove(Subject); 25 | } 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Core/Export/Exporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class Exporter 5 | { 6 | 7 | public abstract Type ResourceType { get; } 8 | 9 | public abstract string Text { get; } 10 | 11 | public abstract bool Export(IUserInterface ui, out ReadOnlySpan buf, object res); 12 | 13 | public virtual string[] FileFilters => new string[0]; 14 | 15 | public static List AllExporters { get; } = 16 | new List(); 17 | 18 | [Registrar.TypeProcessor] 19 | private static void ProcessExporterType(Type type) 20 | { 21 | if (!typeof(Exporter).IsAssignableFrom(type)) 22 | return; 23 | if (type.IsAbstract) 24 | return; 25 | 26 | AllExporters.Add((Exporter)Activator.CreateInstance(type)); 27 | } 28 | 29 | } 30 | 31 | public abstract class Exporter : Exporter 32 | { 33 | 34 | public sealed override Type ResourceType => typeof(T); 35 | 36 | public sealed override bool Export(IUserInterface ui, out ReadOnlySpan buf, object res) 37 | { 38 | ArgumentNullException.ThrowIfNull(ui); 39 | ArgumentNullException.ThrowIfNull(res); 40 | if (!(res is T)) 41 | throw new ArgumentException(); 42 | 43 | return Export(ui, out buf, (T)res); 44 | } 45 | 46 | public abstract bool Export(IUserInterface ui, out ReadOnlySpan buf, T res); 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Core/Gui/UndockCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class UndockCommand : Command 5 | { 6 | 7 | public UndockCommand(MainForm host) : base(host) { } 8 | 9 | public override string Text => "Undock"; 10 | 11 | public override string ImageKey => "Anchor"; 12 | 13 | public override bool Ready => 14 | (WsHost as MainControl)?.ResourceBox?.CanToggleUndock == true; 15 | 16 | public override bool Execute() 17 | { 18 | if (!(WsHost is MainControl mainCtl)) 19 | throw new InvalidOperationException(); 20 | if (!mainCtl.ResourceBox.CanToggleUndock) 21 | throw new InvalidOperationException(); 22 | 23 | mainCtl.ResourceBox.ToggleUndock(); 24 | return true; 25 | } 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Core/IResource.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public interface IResource 5 | { 6 | 7 | public string Title { get; } 8 | 9 | public string ImageKey { get; } 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Core/IUserInterface.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public interface IUserInterface 5 | { 6 | 7 | void ShowError(string msg); 8 | 9 | bool ShowImportDialog(out string? filename, string[] fileFilters); 10 | 11 | bool ShowExportDialog(out string? filename, string[] fileFilters); 12 | 13 | UserChoice? ShowChoiceDialog(string msg, IEnumerable choices); 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Core/Legacy/LegacyEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace CrashEdit 4 | { 5 | 6 | public sealed class LegacyEditor : Editor 7 | { 8 | 9 | public override string Text => 10 | (Control as LegacyEditorControlWrapper)?.InnerControl?.GetType()?.Name ?? "Legacy"; 11 | 12 | public override bool ApplicableForSubject(Controller subj) 13 | { 14 | ArgumentNullException.ThrowIfNull(subj); 15 | 16 | return (subj.Legacy?.EditorAvailable == true); 17 | } 18 | 19 | protected override Control MakeControl() 20 | { 21 | return new LegacyEditorControlWrapper(Subject.Legacy!); 22 | } 23 | 24 | public override void Sync() 25 | { 26 | ((LegacyEditorControlWrapper)Control).Sync(); 27 | } 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Core/Legacy/LegacyEditorControlWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace CrashEdit 4 | { 5 | 6 | public sealed class LegacyEditorControlWrapper : UserControl 7 | { 8 | 9 | public LegacyEditorControlWrapper(LegacyController legacyCtlr) 10 | { 11 | ArgumentNullException.ThrowIfNull(legacyCtlr); 12 | 13 | LegacyController = legacyCtlr; 14 | legacyCtlr.NeedsNewEditor = false; 15 | InnerControl = legacyCtlr.CreateEditor(); 16 | InnerControl.Dock = DockStyle.Fill; 17 | Controls.Add(InnerControl); 18 | } 19 | 20 | public LegacyController LegacyController { get; } 21 | 22 | public Control InnerControl { get; private set; } 23 | 24 | public void Sync() 25 | { 26 | if (LegacyController.NeedsNewEditor) 27 | { 28 | LegacyController.NeedsNewEditor = false; 29 | Controls.Remove(InnerControl); 30 | InnerControl.Dispose(); 31 | InnerControl = LegacyController.CreateEditor(); 32 | InnerControl.Dock = DockStyle.Fill; 33 | Controls.Add(InnerControl); 34 | } 35 | else 36 | { 37 | InnerControl.Invalidate(true); 38 | } 39 | } 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Core/Legacy/LegacyMoveVerb.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class LegacyMoveVerb : TransitiveVerb 5 | { 6 | 7 | public override string Text => "Move here"; 8 | 9 | public override bool ApplicableForSource(Controller src) 10 | { 11 | ArgumentNullException.ThrowIfNull(src); 12 | 13 | return (src.Legacy != null); 14 | } 15 | 16 | public override bool ApplicableForTransit(Controller src, Controller dest) 17 | { 18 | ArgumentNullException.ThrowIfNull(src); 19 | ArgumentNullException.ThrowIfNull(dest); 20 | 21 | if (src.Legacy == null) 22 | return false; 23 | if (dest.Legacy == null) 24 | return false; 25 | 26 | return src.Legacy.CanMoveTo(dest.Legacy); 27 | } 28 | 29 | public override void Execute(IUserInterface ui) 30 | { 31 | ArgumentNullException.ThrowIfNull(ui); 32 | if (Source == null) 33 | throw new InvalidOperationException(); 34 | if (Destination == null) 35 | throw new InvalidOperationException(); 36 | if (Source.Legacy == null) 37 | throw new InvalidOperationException(); 38 | if (Destination.Legacy == null) 39 | throw new InvalidOperationException(); 40 | 41 | Source.Legacy.MoveTo(Destination.Legacy); 42 | } 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Core/Legacy/LegacyVerb.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class LegacyVerb : Verb 5 | { 6 | 7 | public LegacyVerb(string text, Action proc) 8 | { 9 | ArgumentNullException.ThrowIfNull(text); 10 | ArgumentNullException.ThrowIfNull(proc); 11 | 12 | _text = text; 13 | Proc = proc; 14 | } 15 | 16 | public string _text; 17 | 18 | public override string Text => _text; 19 | 20 | private Action Proc { get; } 21 | 22 | public override void Execute(IUserInterface ui) 23 | { 24 | ArgumentNullException.ThrowIfNull(ui); 25 | 26 | Proc(); 27 | } 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Core/Legacy/OrphanLegacyControllerAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | [AttributeUsage(AttributeTargets.Class)] 5 | public sealed class OrphanLegacyControllerAttribute : Attribute 6 | { 7 | 8 | public OrphanLegacyControllerAttribute(Type resType) 9 | { 10 | ArgumentNullException.ThrowIfNull(resType); 11 | 12 | ResourceType = resType; 13 | } 14 | 15 | public Type ResourceType { get; } 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Core/Search/FindFirstCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class FindFirstCommand : Command 5 | { 6 | 7 | public FindFirstCommand(ICommandHost host) : base(host) { } 8 | 9 | public override string Text => "Find First"; 10 | 11 | public override string ImageKey => "RecordFirst"; 12 | 13 | public override bool Ready => 14 | WsHost?.SearchPredicate != null; 15 | 16 | public override bool Execute() 17 | { 18 | if (WsHost == null) 19 | throw new InvalidOperationException(); 20 | if (WsHost.SearchPredicate == null) 21 | throw new InvalidOperationException(); 22 | 23 | // Start from the root controller. 24 | var w = new Walker(); 25 | w.Cursor = WsHost.RootController; 26 | 27 | // Advance depth-first until a match is found. 28 | while (!WsHost.SearchPredicate(w.Cursor)) 29 | { 30 | if (!w.MoveToNextDFS()) 31 | { 32 | // Nothing in the entire tree matches. 33 | Host.ShowError("No results found."); 34 | return false; 35 | } 36 | } 37 | 38 | // Match found. 39 | WsHost.ActiveController = w.Cursor; 40 | return true; 41 | } 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Core/Search/FindLastCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class FindLastCommand : Command 5 | { 6 | 7 | public FindLastCommand(ICommandHost host) : base(host) { } 8 | 9 | public override string Text => "Find Last"; 10 | 11 | public override string ImageKey => "RecordLast"; 12 | 13 | public override bool Ready => 14 | WsHost?.SearchPredicate != null; 15 | 16 | public override bool Execute() 17 | { 18 | if (WsHost == null) 19 | throw new InvalidOperationException(); 20 | if (WsHost.SearchPredicate == null) 21 | throw new InvalidOperationException(); 22 | 23 | // Start from the last (by depth-first) controller. 24 | var w = new Walker(); 25 | w.Cursor = WsHost.RootController; 26 | while (w.MoveToLastChild()) { } 27 | 28 | // Regress depth-first until a match is found. 29 | while (!WsHost.SearchPredicate!(w.Cursor)) 30 | { 31 | if (!w.MoveToPreviousDFS()) 32 | { 33 | // Nothing in the entire tree matches. 34 | Host.ShowError("No results found."); 35 | return false; 36 | } 37 | } 38 | 39 | // Match found. 40 | WsHost.ActiveController = w.Cursor; 41 | return true; 42 | } 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Core/Search/FindNextCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class FindNextCommand : Command 5 | { 6 | 7 | public FindNextCommand(ICommandHost host) : base(host) { } 8 | 9 | public override string Text => "Find Next"; 10 | 11 | public override string ImageKey => "RecordNext"; 12 | 13 | public override bool Ready => 14 | WsHost?.SearchPredicate != null && 15 | WsHost?.ActiveController != null; 16 | 17 | public override bool Execute() 18 | { 19 | if (WsHost == null) 20 | throw new InvalidOperationException(); 21 | if (WsHost.SearchPredicate == null) 22 | throw new InvalidOperationException(); 23 | if (WsHost.ActiveController == null) 24 | throw new InvalidOperationException(); 25 | 26 | // Start from the currently selected controller. 27 | var w = new Walker(); 28 | w.Cursor = WsHost.ActiveController; 29 | 30 | // Advance until a match is found. The initial selection is not eligible. 31 | while (w.MoveToNextDFS()) 32 | { 33 | if (WsHost.SearchPredicate(w.Cursor)) 34 | { 35 | // Match found. 36 | WsHost.ActiveController = w.Cursor; 37 | return true; 38 | } 39 | } 40 | 41 | // No match. 42 | Host.ShowError("No results after the current selection."); 43 | return false; 44 | } 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Core/UserChoice.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public sealed class UserChoice 5 | { 6 | 7 | public string? Text { get; set; } 8 | 9 | public string ImageKey { get; set; } = "Arrow"; 10 | 11 | public object? Tag { get; set; } 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Core/Verb/DirectVerb.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class DirectVerb : Verb 5 | { 6 | 7 | public Controller? Subject { get; set; } 8 | 9 | public abstract bool ApplicableForSubject(Controller subj); 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Core/Verb/GroupVerb.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class GroupVerb : Verb 5 | { 6 | 7 | public SubcontrollerGroup? Group { get; set; } 8 | 9 | public abstract bool ApplicableForGroup(SubcontrollerGroup group); 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Core/Verb/IVerbExecutor.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public interface IVerbExecutor 5 | { 6 | 7 | void ExecuteVerb(Verb verb); 8 | 9 | void ExecuteVerbChoice(List verbs); 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Core/Verb/TransitiveVerb.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class TransitiveVerb : Verb 5 | { 6 | 7 | public Controller? Source { get; set; } 8 | 9 | public Controller? Destination { get; set; } 10 | 11 | public abstract bool ApplicableForSource(Controller src); 12 | 13 | public abstract bool ApplicableForTransit(Controller src, Controller dest); 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Core/Verb/Verb.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class Verb : ICloneable 5 | { 6 | 7 | public abstract string Text { get; } 8 | 9 | public virtual string ImageKey => ""; 10 | 11 | public abstract void Execute(IUserInterface ui); 12 | 13 | public virtual object Clone() 14 | { 15 | return MemberwiseClone(); 16 | } 17 | 18 | public static List AllVerbs { get; } = 19 | new List(); 20 | 21 | [Registrar.TypeProcessor] 22 | private static void ProcessVerbType(Type type) 23 | { 24 | if (!typeof(Verb).IsAssignableFrom(type)) 25 | return; 26 | if (type.IsAbstract) 27 | return; 28 | if (type == typeof(LegacyVerb)) 29 | return; 30 | 31 | AllVerbs.Add((Verb)Activator.CreateInstance(type)); 32 | } 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Core/Workspace.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit 2 | { 3 | 4 | public abstract class Workspace : IResource 5 | { 6 | 7 | public virtual string Title => "Workspace"; 8 | 9 | public virtual string ImageKey => "Sitemap"; 10 | 11 | public virtual void Sync() { } 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Crash.UI/Crash.UI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0-windows 5 | enable 6 | enable 7 | CrashEdit.CrashUI 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Crash.UI/Properties/Resources.ja.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Crash.UI/Properties/Resources.ja.Designer.cs -------------------------------------------------------------------------------- /Crash/Configuration System/GameVersion.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public enum GameVersion 4 | { 5 | None, 6 | Crash1Beta1995, 7 | Crash1BetaMAR08, 8 | Crash1BetaMAY11, 9 | Crash1, 10 | Crash2, 11 | Crash3 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Crash/Editors/UnprocessedChunkHexEditor.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | using System.Windows.Forms; 3 | 4 | namespace CrashEdit 5 | { 6 | public sealed class UnprocessedChunkHexEditor : Editor 7 | { 8 | public override string Text => "Hex"; 9 | 10 | public override bool ApplicableForSubject(Controller subj) 11 | { 12 | ArgumentNullException.ThrowIfNull(subj); 13 | 14 | return subj.Resource is UnprocessedChunk; 15 | } 16 | 17 | protected override Control MakeControl() 18 | { 19 | return new HexView 20 | { 21 | Data = ((UnprocessedChunk)Subject.Resource).Data, 22 | DataChangeHandler = HexView_DataChangeHandler, 23 | }; 24 | } 25 | 26 | private bool HexView_DataChangeHandler(int destOffset, int destLength, byte[] source) 27 | { 28 | var data = ((UnprocessedChunk)Subject.Resource).Data; 29 | 30 | if (destLength != source.Length) 31 | throw new ArgumentException(); 32 | if (destOffset < 0 || destOffset >= data.Length) 33 | throw new ArgumentException(); 34 | 35 | Array.Copy(source, 0, data, destOffset, destLength); 36 | return true; 37 | } 38 | 39 | public override void Sync() 40 | { 41 | ((HexView)Control).Invalidate(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Crash/Error System/EntryAddException.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace CrashEdit.Crash 4 | { 5 | [Serializable] 6 | public class EntryAddException : Exception 7 | { 8 | public EntryAddException(int eid) : base(string.Format("An entry with the name {0} already exists.", Entry.EIDToEName(eid))) 9 | { 10 | EID = eid; 11 | } 12 | 13 | public EntryAddException(int eid, string message) : base(message) 14 | { 15 | EID = eid; 16 | } 17 | 18 | public EntryAddException(int eid, string message, Exception inner) : base(message, inner) 19 | { 20 | EID = eid; 21 | } 22 | 23 | public int EID { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Crash/Error System/ErrorResponse.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public enum ErrorResponse 4 | { 5 | Break, 6 | Abort, 7 | Skip, 8 | Ignore, 9 | IgnoreAll 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Crash/Error System/ErrorSignalEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class ErrorSignalEventArgs : EventArgs 4 | { 5 | public ErrorSignalEventArgs(string message) 6 | { 7 | Message = message; 8 | Response = ErrorResponse.Skip; 9 | CanSkip = false; 10 | CanIgnore = false; 11 | Subject = null; 12 | } 13 | 14 | public string Message { get; set; } 15 | public ErrorResponse Response { get; set; } 16 | public bool CanSkip { get; set; } 17 | public bool CanIgnore { get; set; } 18 | public object Subject { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Crash/Error System/ErrorSignalEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public delegate void ErrorSignalEventHandler(object sender, ErrorSignalEventArgs e); 4 | } 5 | -------------------------------------------------------------------------------- /Crash/Error System/LoadAbortedException.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace CrashEdit.Crash 4 | { 5 | [Serializable] 6 | public class LoadAbortedException : Exception 7 | { 8 | public LoadAbortedException() : base("Loading was aborted while processing this object.") 9 | { 10 | } 11 | 12 | public LoadAbortedException(string message) : base(message) 13 | { 14 | } 15 | 16 | public LoadAbortedException(string message, Exception inner) : base(message, inner) 17 | { 18 | } 19 | 20 | protected LoadAbortedException(SerializationInfo info, StreamingContext context) : base(info, context) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Error System/LoadSkippedException.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace CrashEdit.Crash 4 | { 5 | [Serializable] 6 | public class LoadSkippedException : Exception 7 | { 8 | public LoadSkippedException() : base("Processing of this object was skipped.") 9 | { 10 | } 11 | 12 | public LoadSkippedException(string message) : base(message) 13 | { 14 | } 15 | 16 | public LoadSkippedException(string message, Exception inner) : base(message, inner) 17 | { 18 | } 19 | 20 | protected LoadSkippedException(SerializationInfo info, StreamingContext context) : base(info, context) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Error System/PackingException.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace CrashEdit.Crash 4 | { 5 | [Serializable] 6 | public class PackingException : Exception 7 | { 8 | public PackingException(int eid) : base("The data to be saved was too large to fit into its parent container.") 9 | { 10 | EID = eid; 11 | } 12 | 13 | public PackingException(int eid, string message) : base(message) 14 | { 15 | EID = eid; 16 | } 17 | 18 | public PackingException(int eid, string message, Exception inner) : base(message, inner) 19 | { 20 | EID = eid; 21 | } 22 | 23 | protected PackingException(SerializationInfo info, StreamingContext context) : base(info, context) 24 | { 25 | } 26 | 27 | public int EID { get; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Crash/Formats/Common Formats/RIFF/RIFFData.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class RIFFData : RIFFItem 4 | { 5 | private byte[] data; 6 | 7 | public RIFFData(string name, byte[] data) : base(name) 8 | { 9 | ArgumentNullException.ThrowIfNull(name); 10 | this.data = data ?? throw new ArgumentNullException(nameof(data)); 11 | } 12 | 13 | public override int Length => data.Length + 8; 14 | 15 | public override byte[] Save(Endianness endianness) 16 | { 17 | byte[] result = new byte[8 + data.Length]; 18 | result[0] = (byte)Name[0]; 19 | result[1] = (byte)Name[1]; 20 | result[2] = (byte)Name[2]; 21 | result[3] = (byte)Name[3]; 22 | AutoBitConv.ToInt32(endianness, result, 4, data.Length); 23 | data.CopyTo(result, 8); 24 | return result; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Crash/Formats/Common Formats/RIFF/RIFFItem.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class RIFFItem 4 | { 5 | private string name; 6 | 7 | public RIFFItem(string name) 8 | { 9 | ArgumentNullException.ThrowIfNull(name); 10 | if (name.Length != 4) 11 | throw new ArgumentException("Value must be 4 characters long.", nameof(name)); 12 | this.name = name; 13 | } 14 | 15 | public string Name 16 | { 17 | get => name; 18 | set 19 | { 20 | if (name.Length != 4) 21 | throw new ArgumentException("Value must be 4 characters long.", "name"); 22 | name = value; 23 | } 24 | } 25 | 26 | public abstract int Length { get; } 27 | 28 | public byte[] Save() 29 | { 30 | return Save(Endianness.LittleEndian); 31 | } 32 | 33 | public abstract byte[] Save(Endianness endianness); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/AnimationEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(1, GameVersion.Crash2)] 4 | public sealed class AnimationEntryLoader : EntryLoader 5 | { 6 | public override Entry Load(byte[][] items, int eid) 7 | { 8 | ArgumentNullException.ThrowIfNull(items); 9 | Frame[] frames = new Frame[items.Length]; 10 | for (int i = 0; i < frames.Length; i++) 11 | { 12 | frames[i] = Frame.Load(items[i]); 13 | } 14 | return new AnimationEntry(frames, false, eid); 15 | } 16 | } 17 | 18 | [EntryType(1, GameVersion.Crash3)] 19 | public sealed class NewAnimationEntryLoader : EntryLoader 20 | { 21 | public override Entry Load(byte[][] items, int eid) 22 | { 23 | ArgumentNullException.ThrowIfNull(items); 24 | Frame[] frames = new Frame[items.Length]; 25 | for (int i = 0; i < frames.Length; i++) 26 | { 27 | frames[i] = Frame.LoadNew(items[i]); 28 | } 29 | return new AnimationEntry(frames, true, eid); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/ColoredAnimationEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class ColoredAnimationEntry : Entry 4 | { 5 | public ColoredAnimationEntry(IEnumerable frames, int eid) : base(eid) 6 | { 7 | Frames.AddRange(frames); 8 | } 9 | 10 | public override string Title => $"Colored Animation ({EName})"; 11 | public override string ImageKey => "ThingLime"; 12 | 13 | public override int Type => 20; 14 | 15 | [SubresourceList] 16 | public List Frames { get; } = new List(); 17 | 18 | public override UnprocessedEntry Unprocess() 19 | { 20 | byte[][] items = new byte[Frames.Count][]; 21 | for (int i = 0; i < Frames.Count; i++) 22 | { 23 | items[i] = Frames[i].Save(); 24 | } 25 | return new UnprocessedEntry(items, EID, Type); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/ColoredAnimationEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(20, GameVersion.Crash1BetaMAR08)] 4 | [EntryType(20, GameVersion.Crash1BetaMAY11)] 5 | [EntryType(20, GameVersion.Crash1)] 6 | public sealed class ColoredAnimationEntryLoader : EntryLoader 7 | { 8 | public override Entry Load(byte[][] items, int eid) 9 | { 10 | ArgumentNullException.ThrowIfNull(items); 11 | OldFrame[] frames = new OldFrame[items.Length]; 12 | for (int i = 0; i < frames.Length; i++) 13 | { 14 | frames[i] = OldFrame.Load(items[i]); 15 | } 16 | return new ColoredAnimationEntry(frames, eid); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/FrameCollision.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct FrameCollision 4 | { 5 | public FrameCollision(int u, int xo, int yo, int zo, int x1, int y1, int z1, int x2, int y2, int z2) 6 | { 7 | U = u; 8 | X1 = x1; 9 | Y1 = y1; 10 | Z1 = z1; 11 | X2 = x2; 12 | Y2 = y2; 13 | Z2 = z2; 14 | XOffset = xo; 15 | YOffset = yo; 16 | ZOffset = zo; 17 | } 18 | 19 | public int U { get; set; } 20 | public int XOffset { get; set; } 21 | public int YOffset { get; set; } 22 | public int ZOffset { get; set; } 23 | public int X1 { get; set; } 24 | public int Y1 { get; set; } 25 | public int Z1 { get; set; } 26 | public int X2 { get; set; } 27 | public int Y2 { get; set; } 28 | public int Z2 { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/FrameVertex.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public readonly struct FrameVertex 4 | { 5 | public FrameVertex(byte x, byte y, byte z) 6 | { 7 | X = x; 8 | Y = y; 9 | Z = z; 10 | } 11 | 12 | public byte X { get; } 13 | public byte Y { get; } 14 | public byte Z { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/OldAnimationEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class OldAnimationEntry : Entry 4 | { 5 | public OldAnimationEntry(IEnumerable frames, int eid) : base(eid) 6 | { 7 | Frames.AddRange(frames); 8 | } 9 | 10 | public override string Title => $"Old Animation ({EName})"; 11 | public override string ImageKey => "ThingLime"; 12 | 13 | public override int Type => 1; 14 | 15 | [SubresourceList] 16 | public List Frames { get; } = new List(); 17 | 18 | public override UnprocessedEntry Unprocess() 19 | { 20 | byte[][] items = new byte[Frames.Count][]; 21 | for (int i = 0; i < Frames.Count; i++) 22 | { 23 | items[i] = Frames[i].Save(); 24 | } 25 | return new UnprocessedEntry(items, EID, Type); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/OldAnimationEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(1, GameVersion.Crash1BetaMAR08)] 4 | [EntryType(1, GameVersion.Crash1BetaMAY11)] 5 | [EntryType(1, GameVersion.Crash1)] 6 | public sealed class OldAnimationEntryLoader : EntryLoader 7 | { 8 | public override Entry Load(byte[][] items, int eid) 9 | { 10 | ArgumentNullException.ThrowIfNull(items); 11 | OldFrame[] frames = new OldFrame[items.Length]; 12 | for (int i = 0; i < frames.Length; i++) 13 | { 14 | frames[i] = OldFrame.Load(items[i]); 15 | } 16 | return new OldAnimationEntry(frames, eid); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/ProtoAnimationEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class ProtoAnimationEntry : Entry 4 | { 5 | public ProtoAnimationEntry(IEnumerable frames, bool notproto, int eid) : base(eid) 6 | { 7 | Frames.AddRange(frames); 8 | NotProto = notproto; 9 | } 10 | 11 | public override string Title => 12 | NotProto ? 13 | $"Old Animation ({EName})" : 14 | $"Prototype Animation ({EName})"; 15 | 16 | public override string ImageKey => "ThingLime"; 17 | 18 | public override int Type => 1; 19 | public bool NotProto { get; } 20 | 21 | [SubresourceList] 22 | public List Frames { get; } = new List(); 23 | 24 | public override UnprocessedEntry Unprocess() 25 | { 26 | byte[][] items = new byte[Frames.Count][]; 27 | for (int i = 0; i < Frames.Count; i++) 28 | { 29 | items[i] = Frames[i].Save(); 30 | } 31 | return new UnprocessedEntry(items, EID, Type); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Animation/ProtoAnimationEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(1, GameVersion.Crash1Beta1995)] 4 | public sealed class ProtoAnimationEntryLoader : EntryLoader 5 | { 6 | public override Entry Load(byte[][] items, int eid) 7 | { 8 | ArgumentNullException.ThrowIfNull(items); 9 | OldFrame[] frames = new OldFrame[items.Length]; 10 | for (int i = 0; i < frames.Length; i++) 11 | { 12 | frames[i] = OldFrame.Load(items[i]); 13 | } 14 | return new ProtoAnimationEntry(frames, !frames[0].Proto, eid); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Chunk/ChunkExporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | 4 | public sealed class ChunkExporter : Exporter 5 | { 6 | 7 | public override string Text => "Crash Bandicoot NSF chunk (page)"; 8 | 9 | public override string[] FileFilters => new string[] { 10 | "nschunk files (*.nschunk)|*.nschunk;*.NSCHUNK" 11 | }; 12 | 13 | public override bool Export(IUserInterface ui, out ReadOnlySpan buf, Chunk res) 14 | { 15 | ArgumentNullException.ThrowIfNull(ui); 16 | ArgumentNullException.ThrowIfNull(res); 17 | 18 | buf = new ReadOnlySpan(res.Save()); 19 | return true; 20 | } 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Chunk/ChunkLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class ChunkLoader 4 | { 5 | public abstract Chunk Load(byte[] data); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Chunk/ChunkTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [AttributeUsage(AttributeTargets.Class)] 4 | public sealed class ChunkTypeAttribute : Attribute 5 | { 6 | public ChunkTypeAttribute(short type) 7 | { 8 | Type = type; 9 | } 10 | 11 | public short Type { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Chunk/UnprocessedChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class UnprocessedChunk : Chunk 4 | { 5 | public UnprocessedChunk(byte[] data) 6 | { 7 | ArgumentNullException.ThrowIfNull(data); 8 | if (data.Length != Length) 9 | throw new ArgumentException("Data must be 65536 bytes long."); 10 | Data = data; 11 | } 12 | 13 | public override string Title => $"Unprocessed Chunk T{Type} ({ChunkId:X04})"; 14 | public override string ImageKey => "JournalOrange"; 15 | 16 | public override short Type => BitConv.FromInt16(Data, 2); 17 | public override int ChunkId { get => BitConv.FromInt32(Data, 4); set => BitConv.ToInt32(Data, 4, value); } 18 | 19 | public byte[] Data { get; } 20 | 21 | public Chunk Process() 22 | { 23 | if (loaders.ContainsKey(Type)) 24 | { 25 | return loaders[Type].Load(Data); 26 | } 27 | else 28 | { 29 | ErrorManager.SignalError("UnprocessedChunk: Unknown chunk type"); 30 | return null; 31 | } 32 | } 33 | 34 | public override UnprocessedChunk Unprocess() 35 | { 36 | return this; 37 | } 38 | 39 | public override byte[] Save() 40 | { 41 | int checksum = CalculateChecksum(Data); 42 | BitConv.ToInt32(Data, 12, checksum); 43 | return Data; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Entry/ENameComparer.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class ENameComparer : StringComparer 4 | { 5 | public override int Compare(string a, string b) 6 | { 7 | if (a.Length != 5 || b.Length != 5) throw new ArgumentException("Entry name is not 5 characters long."); 8 | int s = 0; 9 | for (int i = 0; i < 5 && s == 0; ++i) 10 | { 11 | s = Entry.ENameCharacterSet.IndexOf(a[i]) - Entry.ENameCharacterSet.IndexOf(b[i]); 12 | } 13 | return s; 14 | } 15 | 16 | public override int GetHashCode(string obj) 17 | { 18 | return obj.GetHashCode(); 19 | } 20 | 21 | public override bool Equals(string x, string y) 22 | { 23 | return x == y; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Entry/EntryExporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | 4 | public sealed class EntryExporter : Exporter 5 | { 6 | 7 | public override string Text => "Crash Bandicoot NSF entry"; 8 | 9 | public override string[] FileFilters => new string[] { 10 | "nsentry files (*.nsentry)|*.nsentry;*.NSENTRY" 11 | }; 12 | 13 | public override bool Export(IUserInterface ui, out ReadOnlySpan buf, Entry res) 14 | { 15 | ArgumentNullException.ThrowIfNull(ui); 16 | ArgumentNullException.ThrowIfNull(res); 17 | 18 | buf = new ReadOnlySpan(res.Save()); 19 | return true; 20 | } 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Entry/EntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class EntryLoader 4 | { 5 | public abstract Entry Load(byte[][] items, int eid); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Entry/EntryTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 4 | public sealed class EntryTypeAttribute : Attribute 5 | { 6 | public EntryTypeAttribute(int type, GameVersion gameversion) 7 | { 8 | Type = type; 9 | GameVersion = gameversion; 10 | } 11 | 12 | public int Type { get; } 13 | 14 | public GameVersion GameVersion { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Base/Entry/IEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public interface IEntry 4 | { 5 | int EID { get; } 6 | string EName { get; } 7 | int HashKey { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Demo/DemoEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class DemoEntry : MysteryUniItemEntry 4 | { 5 | public DemoEntry(byte[] data, int eid) : base(data, eid) 6 | { 7 | } 8 | 9 | public override string Title => $"Demo ({EName})"; 10 | public override string ImageKey => "ThingOrange"; 11 | 12 | public override int Type => 19; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Demo/DemoEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(19, GameVersion.Crash1BetaMAY11)] 4 | [EntryType(19, GameVersion.Crash1)] 5 | [EntryType(19, GameVersion.Crash2)] 6 | [EntryType(19, GameVersion.Crash3)] 7 | public sealed class DemoEntryLoader : EntryLoader 8 | { 9 | public override Entry Load(byte[][] items, int eid) 10 | { 11 | if (items.Length != 1) 12 | { 13 | ErrorManager.SignalError("DemoEntry: Wrong number of items"); 14 | } 15 | return new DemoEntry(items[0], eid); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/FontTexture.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class FontTexture(int packed1, int packed2, short width, short height) : SpriteTexture(packed1, packed2) 4 | { 5 | public short Width { get; set; } = width; 6 | public short Height { get; set; } = height; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/FontTexture2.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class FontTexture2(int packed1, int packed2, int packed3, int packed4, short width, short height) : SpriteTexture2(packed1, packed2, packed3, packed4) 4 | { 5 | public short Width { get; set; } = width; 6 | public short Height { get; set; } = height; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/ImageTexture.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class ImageTexture(int packed1, int packed2, short x1, short y1, short x2, short y2) : SpriteTexture(packed1, packed2) 4 | { 5 | public short X1 { get; set; } = x1; 6 | public short Y1 { get; set; } = y1; 7 | public short X2 { get; set; } = x2; 8 | public short Y2 { get; set; } = y2; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/ImageTexture2.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class ImageTexture2(int packed1, int packed2, int packed3, int packed4, short x1, short y1, short x2, short y2) : SpriteTexture2(packed1, packed2, packed3, packed4) 4 | { 5 | public short X1 { get; set; } = x1; 6 | public short Y1 { get; set; } = y1; 7 | public short X2 { get; set; } = x2; 8 | public short Y2 { get; set; } = y2; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/ProtoSpriteTexture.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class ProtoSpriteTexture(int packed1, int packed2) : GOOLFrameGroupBase 4 | { 5 | public int PackedValue1 = packed1; 6 | public int PackedValue2 = packed2; 7 | 8 | public int R => (PackedValue1) & 0xff; 9 | public int G => (PackedValue1 >> 8) & 0xff; 10 | public int B => (PackedValue1 >> 16) & 0xff; 11 | public int ClutX => (PackedValue1 >> 24) & 0xf; 12 | public int Unk1 => (PackedValue1 >> 28) & 0x1; 13 | public int BlendMode => (PackedValue1 >> 29) & 0x3; 14 | public int Textured => (PackedValue1 >> 31) & 0x1; 15 | public int Y => (PackedValue2) & 0x1f; 16 | public int Unk2 => (PackedValue2 >> 5) & 0x1; 17 | public int ClutY => (PackedValue2 >> 6) & 0x7f; 18 | public int X => (PackedValue2 >> 13) & 0x1f; 19 | public int Segment => (PackedValue2 >> 18) & 0x3; 20 | public int ColorMode => (PackedValue2 >> 20) & 0x3; 21 | public int UV => (PackedValue2 >> 22) & 0x3ff; 22 | 23 | public override byte[] Save() 24 | { 25 | byte[] data = new byte[8]; 26 | BitConv.ToInt32(data, 0, PackedValue1); 27 | BitConv.ToInt32(data, 4, PackedValue2); 28 | return data; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/SpriteTexture.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class SpriteTexture(int packed1, int packed2) 4 | { 5 | public int PackedValue1 = packed1; 6 | public int PackedValue2 = packed2; 7 | 8 | public int R => (PackedValue1) & 0xff; 9 | public int G => (PackedValue1 >> 8) & 0xff; 10 | public int B => (PackedValue1 >> 16) & 0xff; 11 | public int ClutX => (PackedValue1 >> 24) & 0xf; 12 | public int Unk1 => (PackedValue1 >> 28) & 0x1; 13 | public int BlendMode => (PackedValue1 >> 29) & 0x3; 14 | public int Textured => (PackedValue1 >> 31) & 0x1; 15 | public int Y => (PackedValue2) & 0x1f; 16 | public int Unk2 => (PackedValue2 >> 5) & 0x1; 17 | public int ClutY => (PackedValue2 >> 6) & 0x7f; 18 | public int X => (PackedValue2 >> 13) & 0x1f; 19 | public int Segment => (PackedValue2 >> 18) & 0x3; 20 | public int ColorMode => (PackedValue2 >> 20) & 0x3; 21 | public int UV => (PackedValue2 >> 22) & 0x3ff; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/VertexGroup.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class VertexGroup(short frames, int eid) : GOOLFrameGroupWithChunk(eid) 4 | { 5 | public override short Type() => 1; 6 | 7 | public static VertexGroup Load(byte[] data, ref int index) 8 | { 9 | if (BitConv.FromInt16(data, index) != 1) 10 | { 11 | ErrorManager.SignalError("Vertex frame group version is wrong"); 12 | } 13 | index += 2; 14 | 15 | short frames = BitConv.FromInt16(data, index); 16 | index += 2; 17 | 18 | int eid = BitConv.FromInt32(data, index); 19 | index += 4; 20 | 21 | return new VertexGroup(frames, eid); 22 | } 23 | 24 | public short FrameCount { get; set; } = frames; 25 | 26 | public override byte[] Save() 27 | { 28 | byte[] data = new byte[8]; 29 | BitConv.ToInt16(data, 0, Type()); 30 | BitConv.ToInt16(data, 2, FrameCount); 31 | BitConv.ToInt32(data, 4, EID); 32 | return data; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/Frame Groups/VertexGroup2.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class VertexGroup2(bool lerp, short frames, int eid) : GOOLFrameGroupWithChunk(eid) 4 | { 5 | public override short Type() => 1; 6 | 7 | public static VertexGroup2 Load(byte[] data, ref int index) 8 | { 9 | if (BitConv.FromInt16(data, index) != 1) 10 | { 11 | ErrorManager.SignalError("Vertex frame group version is wrong"); 12 | } 13 | index += 2; 14 | 15 | short frames = BitConv.FromInt16(data, index); 16 | index += 2; 17 | 18 | int eid = BitConv.FromInt32(data, index); 19 | index += 4; 20 | 21 | int lerp = BitConv.FromInt32(data, index); 22 | index += 4; 23 | 24 | return new VertexGroup2(lerp != 0, frames, eid); 25 | } 26 | 27 | public short FrameCount { get; set; } = frames; 28 | public bool Interpolated { get; set; } = lerp; 29 | 30 | public override byte[] Save() 31 | { 32 | byte[] data = new byte[12]; 33 | BitConv.ToInt16(data, 0, Type()); 34 | BitConv.ToInt16(data, 2, FrameCount); 35 | BitConv.ToInt32(data, 4, EID); 36 | BitConv.ToInt32(data, 8, Interpolated ? 1 : 0); 37 | return data; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/GOOLArgument.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public enum GOOLArgumentTypes 4 | { 5 | Value, 6 | Ref, 7 | ProcessField, 8 | DestRef, 9 | None, 10 | Signed 11 | } 12 | 13 | public readonly struct GOOLArgument 14 | { 15 | public GOOLArgument(int value, GOOLArgumentTypes type = GOOLArgumentTypes.Value) 16 | { 17 | Value = value; 18 | Type = type; 19 | } 20 | 21 | public int Value { get; } 22 | public GOOLArgumentTypes Type { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/GOOLFrameGroup.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class GOOLFrameGroup : GOOLFrameGroupWithChunk where T : class 4 | { 5 | public short FrameCount => (short)Frames.Count; 6 | public List Frames { get; set; } 7 | 8 | public GOOLFrameGroup(List frames, int eid) : base(eid) 9 | { 10 | Frames = frames; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/GOOLFrameGroupBase.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class GOOLFrameGroupBase 4 | { 5 | public GOOLFrameGroupBase() 6 | { 7 | } 8 | 9 | public abstract byte[] Save(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/GOOLFrameGroupWithChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class GOOLFrameGroupWithChunk : GOOLFrameGroupBase 4 | { 5 | public abstract short Type(); 6 | 7 | public int EID { get; set; } 8 | 9 | public GOOLFrameGroupWithChunk(int eid) 10 | { 11 | EID = eid; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/GOOLInstructionAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 4 | public sealed class GOOLInstructionAttribute : Attribute 5 | { 6 | public GOOLInstructionAttribute(int opcode, GameVersion gameversion) 7 | { 8 | Opcode = opcode; 9 | Version = GOOLInterpreter.GetVersion(gameversion); 10 | } 11 | 12 | public GOOLInstructionAttribute(int opcode, GOOLVersion goolversion) 13 | { 14 | Opcode = opcode; 15 | Version = goolversion; 16 | } 17 | 18 | public int Opcode { get; } 19 | public GOOLVersion Version { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/GOOLStateDescriptor.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct GOOLStateDescriptor 4 | { 5 | public GOOLStateDescriptor(int stateflags, int cflags, short goolid, short epc, short tpc, short cpc) 6 | { 7 | StateFlags = stateflags; 8 | BlockFlags = cflags; 9 | GOOLIndex = goolid; 10 | EventHook = epc; 11 | TransHook = tpc; 12 | CodeHook = cpc; 13 | } 14 | 15 | public int StateFlags { get; } 16 | public int BlockFlags { get; } 17 | public short GOOLIndex { get; } 18 | public short EventHook { get; } 19 | public short TransHook { get; } 20 | public short CodeHook { get; } 21 | 22 | public byte[] Save() 23 | { 24 | byte[] result = new byte[16]; 25 | BitConv.ToInt32(result, 0x0, StateFlags); 26 | BitConv.ToInt32(result, 0x4, BlockFlags); 27 | BitConv.ToInt16(result, 0x8, GOOLIndex); 28 | BitConv.ToInt16(result, 0xA, EventHook); 29 | BitConv.ToInt16(result, 0xC, TransHook); 30 | BitConv.ToInt16(result, 0xE, CodeHook); 31 | return result; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/GOOL/GOOLUnknownInstruction.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public class GOOLUnknownInstruction : GOOLInstruction 4 | { 5 | public GOOLUnknownInstruction(int value, GOOLEntry gool) : base(value, gool, null) { } 6 | 7 | public override string GetName() => $"INS{Opcode}"; 8 | public override string GetFormat() => "IIIIIIIIIIIIIIIIIIIIIIII"; 9 | public override string GetComment() => $"invalid opcode {Opcode}"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Image/ImageEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class ImageEntry : MysteryMultiItemEntry 4 | { 5 | public ImageEntry(IEnumerable items, int eid) : base(items, eid) 6 | { 7 | } 8 | 9 | public override string Title => $"Image ({EName})"; 10 | public override string ImageKey => "Painting"; 11 | 12 | public override int Type => 15; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Image/ImageEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(15, GameVersion.Crash1Beta1995)] 4 | [EntryType(15, GameVersion.Crash1BetaMAR08)] 5 | [EntryType(15, GameVersion.Crash1BetaMAY11)] 6 | [EntryType(15, GameVersion.Crash1)] 7 | public sealed class ImageEntryLoader : EntryLoader 8 | { 9 | public override Entry Load(byte[][] items, int eid) 10 | { 11 | ArgumentNullException.ThrowIfNull(items); 12 | return new ImageEntry(items, eid); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Map/MapEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class MapEntry : Entry 4 | { 5 | public MapEntry(byte[] header, byte[] layout, IEnumerable entities, int eid) : base(eid) 6 | { 7 | Header = header; 8 | Layout = layout; 9 | Entities.AddRange(entities); 10 | } 11 | 12 | public override string Title => $"Map ({EName})"; 13 | public override string ImageKey => "ThingOrange"; 14 | 15 | public override int Type => 17; 16 | 17 | [SubresourceSlot] 18 | public byte[] Header { get; set; } 19 | 20 | [SubresourceSlot] 21 | public byte[] Layout { get; set; } 22 | 23 | [SubresourceList] 24 | public List Entities { get; } = new List(); 25 | 26 | public override UnprocessedEntry Unprocess() 27 | { 28 | BitConv.ToInt32(Header, 0xC, Entities.Count); 29 | byte[][] items = new byte[2 + Entities.Count][]; 30 | items[0] = Header; 31 | items[1] = Layout; 32 | for (int i = 0; i < Entities.Count; i++) 33 | { 34 | items[2 + i] = Entities[i].Save(); 35 | } 36 | return new UnprocessedEntry(items, EID, Type); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Map/MapEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(17, GameVersion.Crash1BetaMAR08)] 4 | [EntryType(17, GameVersion.Crash1BetaMAY11)] 5 | [EntryType(17, GameVersion.Crash1)] 6 | [EntryType(17, GameVersion.Crash2)] 7 | public sealed class MapEntryLoader : EntryLoader 8 | { 9 | public override Entry Load(byte[][] items, int eid) 10 | { 11 | ArgumentNullException.ThrowIfNull(items); 12 | if (items.Length < 2) 13 | { 14 | ErrorManager.SignalError("MapEntry: Wrong number of items"); 15 | } 16 | byte[] header = items[0]; 17 | byte[] layout = items[1]; 18 | int entitycount = BitConv.FromInt32(header, 0xC); 19 | OldEntity[] entities = new OldEntity[entitycount]; 20 | for (int i = 0; i < entitycount; ++i) 21 | { 22 | entities[i] = OldEntity.Load(items[i + 2]); 23 | } 24 | return new MapEntry(header, layout, entities, eid); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Model/ModelPosition.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct ModelPosition 4 | { 5 | public static ModelPosition Load(byte[] data) 6 | { 7 | ArgumentNullException.ThrowIfNull(data); 8 | if (data.Length != 4) 9 | throw new ArgumentException("Value must be 4 bytes long.", nameof(data)); 10 | int structure = BitConv.FromInt32(data, 0); 11 | return new ModelPosition(structure); 12 | } 13 | 14 | public ModelPosition(int structure) 15 | { 16 | X = (byte)((structure >> 25) & 0x7F); 17 | Z = (byte)(structure >> 17); 18 | Y = (byte)(structure >> 9); 19 | XBits = (byte)((structure >> 6) & 0x7); 20 | ZBits = (byte)((structure >> 3) & 0x7); 21 | YBits = (byte)(structure & 0x7); 22 | } 23 | 24 | public byte X { get; } 25 | public byte Z { get; } 26 | public byte Y { get; } 27 | public byte XBits { get; } 28 | public byte ZBits { get; } 29 | public byte YBits { get; } 30 | 31 | public byte[] Save() 32 | { 33 | byte[] result = new byte[4]; 34 | result[0] = (byte)((XBits << 6) | (ZBits << 3) | YBits); 35 | result[1] = (byte)((Y << 1) | (XBits >> 2)); 36 | result[2] = (byte)((Z << 1) | (Y >> 7)); 37 | result[3] = (byte)((X << 1) | (Z >> 7)); 38 | return result; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Model/ModelTransformedTriangle.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct ModelTransformedTriangle 4 | { 5 | public ModelTransformedTriangle(int v1, int v2, int v3, int c1, int c2, int c3, int tex, int type, int subtype, bool animated) 6 | { 7 | Vertex = new int[3] { v1, v2, v3 }; 8 | Color = new int[3] { c1, c2, c3 }; 9 | Texture = tex; 10 | Type = type; 11 | Subtype = subtype; 12 | Animated = animated; 13 | } 14 | 15 | public int[] Vertex { get; } 16 | public int[] Color { get; } 17 | public int Texture { get; } 18 | public int Type { get; } 19 | public int Subtype { get; } 20 | public bool Animated { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Model/OldModelStruct.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public interface OldModelStruct 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Music/OldMusicEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(13, GameVersion.Crash1BetaMAR08)] 4 | public sealed class OldMusicEntryLoader : EntryLoader 5 | { 6 | public override Entry Load(byte[][] items, int eid) 7 | { 8 | ArgumentNullException.ThrowIfNull(items); 9 | if (items.Length != 3) 10 | { 11 | ErrorManager.SignalError("OldMusicEntry: Wrong number of items"); 12 | } 13 | if (items[0].Length != 20) 14 | { 15 | ErrorManager.SignalError("OldMusicEntry: First item length is wrong"); 16 | } 17 | int seqcount = BitConv.FromInt32(items[0], 0); 18 | int vb0eid = BitConv.FromInt32(items[0], 4); 19 | int vb1eid = BitConv.FromInt32(items[0], 8); 20 | int vb2eid = BitConv.FromInt32(items[0], 12); 21 | int vb3eid = BitConv.FromInt32(items[0], 16); 22 | VH vh = VH.Load(items[1]); 23 | SEP sep = SEP.Load(items[2], seqcount); 24 | return new OldMusicEntry(vb0eid, vb1eid, vb2eid, vb3eid, vh, sep, eid); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Mystery/MysteryMultiItemEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class MysteryMultiItemEntry : Entry 4 | { 5 | private List items; 6 | 7 | public MysteryMultiItemEntry(IEnumerable items, int eid) : base(eid) 8 | { 9 | ArgumentNullException.ThrowIfNull(items); 10 | this.items = new List(items); 11 | } 12 | 13 | [SubresourceList] 14 | public IList Items => items; 15 | 16 | public override UnprocessedEntry Unprocess() 17 | { 18 | return new UnprocessedEntry(items, EID, Type); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Mystery/MysteryUniItemEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class MysteryUniItemEntry : Entry 4 | { 5 | public MysteryUniItemEntry(byte[] data, int eid) : base(eid) 6 | { 7 | Data = data ?? throw new ArgumentNullException(nameof(data)); 8 | } 9 | 10 | public byte[] Data { get; } 11 | 12 | public override UnprocessedEntry Unprocess() 13 | { 14 | byte[][] items = new byte[1][]; 15 | items[0] = Data; 16 | int size = Data.Length; 17 | return new UnprocessedEntry(items, EID, Type); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/NSD/NSDLink.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class NSDLink 4 | { 5 | public NSDLink(int chunkid, int entryid) 6 | { 7 | ChunkID = chunkid; 8 | EntryID = entryid; 9 | } 10 | 11 | public int ChunkID { get; set; } 12 | public int EntryID { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/NSD/NSDSpawnPoint.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class NSDSpawnPoint 4 | { 5 | public NSDSpawnPoint(int zoneeid, int camera, int unknown, int spawnx, int spawny, int spawnz) 6 | { 7 | ZoneEID = zoneeid; 8 | Camera = camera; 9 | Unknown = unknown; 10 | SpawnX = spawnx; 11 | SpawnY = spawny; 12 | SpawnZ = spawnz; 13 | } 14 | 15 | public int ZoneEID { get; set; } 16 | public int Camera { get; set; } 17 | public int Unknown { get; set; } 18 | public int SpawnX { get; set; } 19 | public int SpawnY { get; set; } 20 | public int SpawnZ { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Normal/NormalChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class NormalChunk : EntryChunk 4 | { 5 | public NormalChunk() 6 | { 7 | } 8 | 9 | public NormalChunk(IEnumerable entries) : base(entries) 10 | { 11 | } 12 | 13 | public override string Title => $"Chunk {ChunkId}"; 14 | public override string ImageKey => "JournalOrange"; 15 | 16 | public override short Type => 0; 17 | public override int Alignment => 4; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Normal/NormalChunkLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [ChunkType(0)] 4 | public sealed class NormalChunkLoader : EntryChunkLoader 5 | { 6 | public override EntryChunk Load(Entry[] entries) 7 | { 8 | ArgumentNullException.ThrowIfNull(entries); 9 | return new NormalChunk(entries); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Palette/PaletteEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class PaletteEntry : Entry 4 | { 5 | public PaletteEntry(IEnumerable items, int eid) : base(eid) 6 | { 7 | Palettes = new List(items).ToArray(); 8 | } 9 | 10 | public override string Title => $"Palette ({EName})"; 11 | public override string ImageKey => "ThingYellow"; 12 | 13 | public override int Type => 18; 14 | public byte[][] Palettes { get; } 15 | 16 | public override UnprocessedEntry Unprocess() 17 | { 18 | byte[][] items = new byte[Palettes.Length][]; 19 | for (int i = 0; i < Palettes.Length; i++) 20 | { 21 | items[i] = Palettes[i]; 22 | } 23 | return new UnprocessedEntry(items, EID, Type); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Palette/PaletteEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(18, GameVersion.Crash1BetaMAR08)] 4 | [EntryType(18, GameVersion.Crash1BetaMAY11)] 5 | [EntryType(18, GameVersion.Crash1)] 6 | public sealed class PaletteEntryLoader : EntryLoader 7 | { 8 | public override Entry Load(byte[][] items, int eid) 9 | { 10 | ArgumentNullException.ThrowIfNull(items); 11 | return new PaletteEntry(items, eid); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/SLST/OldSLSTEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(4, GameVersion.Crash1Beta1995)] 4 | [EntryType(4, GameVersion.Crash1BetaMAR08)] 5 | [EntryType(4, GameVersion.Crash1BetaMAY11)] 6 | [EntryType(4, GameVersion.Crash1)] 7 | public sealed class OldSLSTEntryLoader : EntryLoader 8 | { 9 | public override Entry Load(byte[][] items, int eid) 10 | { 11 | ArgumentNullException.ThrowIfNull(items); 12 | if (items.Length < 2) 13 | ErrorManager.SignalError("OldSLSTEntry: Item count is wrong"); 14 | OldSLSTSource sourcestart = OldSLSTSource.Load(items[0]); 15 | OldSLSTDelta[] deltas = new OldSLSTDelta[items.Length - 2]; 16 | for (int i = 0; i < items.Length - 2; i++) 17 | { 18 | deltas[i] = OldSLSTDelta.Load(items[i + 1]); 19 | } 20 | OldSLSTSource sourceend = OldSLSTSource.Load(items[items.Length - 1]); 21 | return new OldSLSTEntry(sourcestart, sourceend, deltas, eid); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/SLST/OldSLSTPolygonID.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct OldSLSTPolygonID 4 | { 5 | short poly; 6 | 7 | public OldSLSTPolygonID(short poly) 8 | { 9 | this.poly = poly; 10 | } 11 | 12 | public OldSLSTPolygonID(int id, int world, bool copy) 13 | { 14 | poly = unchecked((short)(id & 0xFFF | (world << 12) | ((copy ? 1 : 0) << 15))); 15 | } 16 | 17 | public int Poly => poly; 18 | public int ID => poly & 0xFFF; 19 | public int World => (poly >> 12) & 0x7; 20 | public int Copy => (poly >> 15) & 0x1; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/SLST/SLSTEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class SLSTEntry : Entry 4 | { 5 | public SLSTEntry(SLSTSource start, SLSTSource end, IEnumerable deltas, int eid) : base(eid) 6 | { 7 | ArgumentNullException.ThrowIfNull(deltas); 8 | Deltas.AddRange(deltas); 9 | Start = start; 10 | End = end; 11 | } 12 | 13 | public override string Title => $"Sort List ({EName})"; 14 | public override string ImageKey => "ThingGray"; 15 | 16 | public override int Type => 4; 17 | 18 | [SubresourceSlot] 19 | public SLSTSource Start { get; } 20 | 21 | [SubresourceList] 22 | public List Deltas { get; } = new List(); 23 | 24 | [SubresourceSlot] 25 | public SLSTSource End { get; } 26 | 27 | public override UnprocessedEntry Unprocess() 28 | { 29 | byte[][] items = new byte[Deltas.Count + 2][]; 30 | items[0] = Start.Save(); 31 | for (int i = 0; i < Deltas.Count; ++i) 32 | { 33 | items[1 + i] = Deltas[i].Save(); 34 | } 35 | items[1 + Deltas.Count] = End.Save(); 36 | return new UnprocessedEntry(items, EID, Type); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/SLST/SLSTEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(4, GameVersion.Crash2)] 4 | [EntryType(4, GameVersion.Crash3)] 5 | public sealed class SLSTEntryLoader : EntryLoader 6 | { 7 | public override Entry Load(byte[][] items, int eid) 8 | { 9 | ArgumentNullException.ThrowIfNull(items); 10 | if (items.Length < 2) 11 | ErrorManager.SignalError("SLSTEntry: Item count is wrong"); 12 | SLSTSource sourcestart = SLSTSource.Load(items[0]); 13 | SLSTDelta[] deltas = new SLSTDelta[items.Length - 2]; 14 | for (int i = 0; i < items.Length - 2; i++) 15 | { 16 | deltas[i] = SLSTDelta.Load(items[i + 1]); 17 | } 18 | SLSTSource sourceend = SLSTSource.Load(items[items.Length - 1]); 19 | return new SLSTEntry(sourcestart, sourceend, deltas, eid); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/SLST/SLSTPolygonID.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct SLSTPolygonID 4 | { 5 | short poly; 6 | 7 | public SLSTPolygonID(short poly) 8 | { 9 | this.poly = poly; 10 | } 11 | 12 | public SLSTPolygonID(int id, int state, int world) 13 | { 14 | poly = unchecked((short)(id & 0x7FF | (state << 11) | (world << 13))); 15 | } 16 | 17 | public int Poly => poly; 18 | public int ID => poly & 0x7FF; 19 | public int State => (poly >> 11) & 0x3; 20 | public int World => (poly >> 13) & 0x7; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Scenery/OldSceneryColor.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct OldSceneryColor : OldModelStruct 4 | { 5 | public byte R { get; } 6 | public byte G { get; } 7 | public byte B { get; } 8 | public bool N { get; } 9 | 10 | public static OldSceneryColor Load(byte[] data) 11 | { 12 | byte r = data[0]; 13 | byte g = data[1]; 14 | byte b = data[2]; 15 | bool n = (data[3] & 0x10) != 0; 16 | return new OldSceneryColor(r, g, b, n); 17 | } 18 | 19 | public OldSceneryColor(byte r, byte g, byte b, bool n) 20 | { 21 | R = r; 22 | G = g; 23 | B = b; 24 | N = n; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Scenery/ProtoSceneryVertex.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public readonly struct ProtoSceneryVertex 4 | { 5 | public static ProtoSceneryVertex Load(byte[] data) 6 | { 7 | ArgumentNullException.ThrowIfNull(data); 8 | if (data.Length != 6) 9 | throw new ArgumentException("Value must be 6 bytes long.", nameof(data)); 10 | short x = BitConv.FromInt16(data, 0); 11 | short y = BitConv.FromInt16(data, 2); 12 | short z = BitConv.FromInt16(data, 4); 13 | return new ProtoSceneryVertex(x, y, z); 14 | } 15 | 16 | public ProtoSceneryVertex(short x, short y, short z) 17 | { 18 | X = x; 19 | Y = y; 20 | Z = z; 21 | } 22 | 23 | public short X { get; } 24 | public short Y { get; } 25 | public short Z { get; } 26 | 27 | public byte[] Save() 28 | { 29 | byte[] result = new byte[6]; 30 | BitConv.ToInt16(result, 0, X); 31 | BitConv.ToInt16(result, 2, Y); 32 | BitConv.ToInt16(result, 4, Z); 33 | return result; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Scenery/SceneryColor.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public readonly struct SceneryColor 4 | { 5 | public SceneryColor(byte red, byte green, byte blue) : this(red, green, blue, 0) 6 | { 7 | } 8 | 9 | public SceneryColor(byte red, byte green, byte blue, byte extra) 10 | { 11 | Red = red; 12 | Green = green; 13 | Blue = blue; 14 | Extra = extra; 15 | } 16 | 17 | public byte Red { get; } 18 | public byte Green { get; } 19 | public byte Blue { get; } 20 | public byte Extra { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Sound/OldSoundChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class OldSoundChunk : EntryChunk 4 | { 5 | public OldSoundChunk() 6 | { 7 | } 8 | 9 | public OldSoundChunk(IEnumerable entries) : base(entries) 10 | { 11 | } 12 | 13 | public override string Title => $"Old Sound Chunk {ChunkId}"; 14 | public override string ImageKey => "JournalBlue"; 15 | 16 | public override short Type => 2; 17 | public override int Alignment => 16; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Sound/OldSoundChunkLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [ChunkType(2)] 4 | public sealed class OldSoundChunkLoader : EntryChunkLoader 5 | { 6 | public override EntryChunk Load(Entry[] entries) 7 | { 8 | ArgumentNullException.ThrowIfNull(entries); 9 | return new OldSoundChunk(entries); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Sound/SoundChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class SoundChunk : EntryChunk 4 | { 5 | public SoundChunk() 6 | { 7 | } 8 | 9 | public SoundChunk(IEnumerable entries) : base(entries) 10 | { 11 | } 12 | 13 | public override string Title => $"Sound Chunk {ChunkId}"; 14 | public override string ImageKey => "JournalBlue"; 15 | 16 | public override short Type => 3; 17 | public override int Alignment => 16; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Sound/SoundChunkLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [ChunkType(3)] 4 | public sealed class SoundChunkLoader : EntryChunkLoader 5 | { 6 | public override EntryChunk Load(Entry[] entries) 7 | { 8 | ArgumentNullException.ThrowIfNull(entries); 9 | return new SoundChunk(entries); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Sound/SoundEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class SoundEntry : Entry 4 | { 5 | public SoundEntry(SampleSet samples, int eid) : base(eid) 6 | { 7 | Samples = samples ?? throw new ArgumentNullException(nameof(samples)); 8 | } 9 | 10 | public override string Title => $"Sound ({EName})"; 11 | public override string ImageKey => "SpeakerBlue"; 12 | 13 | public override int Type => 12; 14 | public SampleSet Samples { get; } 15 | 16 | public override UnprocessedEntry Unprocess() 17 | { 18 | byte[][] items = new byte[1][]; 19 | items[0] = Samples.Save(); 20 | return new UnprocessedEntry(items, EID, Type); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Sound/SoundEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(12, GameVersion.Crash1Beta1995)] 4 | [EntryType(12, GameVersion.Crash1BetaMAR08)] 5 | [EntryType(12, GameVersion.Crash1BetaMAY11)] 6 | [EntryType(12, GameVersion.Crash1)] 7 | [EntryType(12, GameVersion.Crash2)] 8 | [EntryType(12, GameVersion.Crash3)] 9 | public sealed class SoundEntryLoader : EntryLoader 10 | { 11 | public override Entry Load(byte[][] items, int eid) 12 | { 13 | ArgumentNullException.ThrowIfNull(items); 14 | if (items.Length != 1) 15 | { 16 | ErrorManager.SignalError("SoundEntry: Wrong number of items"); 17 | } 18 | return new SoundEntry(SampleSet.Load(items[0]), eid); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Speech/SpeechChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class SpeechChunk : EntryChunk 4 | { 5 | public SpeechChunk() 6 | { 7 | } 8 | 9 | public SpeechChunk(IEnumerable entries) : base(entries) 10 | { 11 | } 12 | 13 | public override string Title => $"Speech Chunk {ChunkId}"; 14 | public override string ImageKey => "JournalWhite"; 15 | 16 | public override short Type => 5; 17 | public override int Alignment => 16; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Speech/SpeechChunkLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [ChunkType(5)] 4 | public sealed class SpeechChunkLoader : EntryChunkLoader 5 | { 6 | public override EntryChunk Load(Entry[] entries) 7 | { 8 | ArgumentNullException.ThrowIfNull(entries); 9 | return new SpeechChunk(entries); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Speech/SpeechEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class SpeechEntry : Entry 4 | { 5 | public SpeechEntry(SampleSet samples, int eid) : base(eid) 6 | { 7 | Samples = samples ?? throw new ArgumentNullException(nameof(samples)); 8 | } 9 | 10 | public override string Title => $"Speech ({EName})"; 11 | public override string ImageKey => "SpeakerWhite"; 12 | 13 | public override int Type => 20; 14 | public SampleSet Samples { get; } 15 | 16 | public override UnprocessedEntry Unprocess() 17 | { 18 | byte[][] items = new byte[1][]; 19 | items[0] = Samples.Save(); 20 | return new UnprocessedEntry(items, EID, Type); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Speech/SpeechEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(20, GameVersion.Crash2)] 4 | [EntryType(20, GameVersion.Crash3)] 5 | public sealed class SpeechEntryLoader : EntryLoader 6 | { 7 | public override Entry Load(byte[][] items, int eid) 8 | { 9 | ArgumentNullException.ThrowIfNull(items); 10 | if (items.Length != 1) 11 | { 12 | ErrorManager.SignalError("SpeechEntry: Wrong number of items"); 13 | } 14 | return new SpeechEntry(SampleSet.Load(items[0]), eid); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T15/T15Entry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class T15Entry : MysteryUniItemEntry 4 | { 5 | public T15Entry(byte[] data, int eid) : base(data, eid) 6 | { 7 | } 8 | 9 | public override string Title => $"T15 ({EName})"; 10 | public override string ImageKey => "ThingOrange"; 11 | 12 | public override int Type => 15; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T15/T15EntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(15, GameVersion.Crash2)] 4 | [EntryType(15, GameVersion.Crash3)] 5 | public sealed class T15EntryLoader : EntryLoader 6 | { 7 | public override Entry Load(byte[][] items, int eid) 8 | { 9 | ArgumentNullException.ThrowIfNull(items); 10 | if (items.Length != 1) 11 | { 12 | ErrorManager.SignalError("T15Entry: Wrong number of items"); 13 | } 14 | return new T15Entry(items[0], eid); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T17/T17Entry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class T17Entry : MysteryMultiItemEntry 4 | { 5 | public T17Entry(IEnumerable items, int eid) : base(items, eid) 6 | { 7 | } 8 | 9 | public override string Title => $"T17 ({EName})"; 10 | public override string ImageKey => "ThingOrange"; 11 | 12 | public override int Type => 17; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T17/T17EntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(17, GameVersion.Crash3)] 4 | public sealed class T17EntryLoader : EntryLoader 5 | { 6 | public override Entry Load(byte[][] items, int eid) 7 | { 8 | ArgumentNullException.ThrowIfNull(items); 9 | return new T17Entry(items, eid); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T21/T21Entry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class T21Entry : MysteryMultiItemEntry 4 | { 5 | public T21Entry(IEnumerable items, int eid) : base(items, eid) 6 | { 7 | } 8 | 9 | public override string Title => $"T21 ({EName})"; 10 | public override string ImageKey => "Painting"; 11 | 12 | public override int Type => 21; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T21/T21EntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(21, GameVersion.Crash2)] 4 | [EntryType(21, GameVersion.Crash3)] 5 | public sealed class T21EntryLoader : EntryLoader 6 | { 7 | public override Entry Load(byte[][] items, int eid) 8 | { 9 | ArgumentNullException.ThrowIfNull(items); 10 | return new T21Entry(items, eid); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T6/T6Entry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class T6Entry : MysteryUniItemEntry 4 | { 5 | public T6Entry(byte[] data, int eid) : base(data, eid) 6 | { 7 | } 8 | 9 | public override string Title => $"T6 ({EName})"; 10 | public override string ImageKey => "ThingOrange"; 11 | 12 | public override int Type => 6; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/T6/T6EntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(6, GameVersion.Crash1Beta1995)] 4 | [EntryType(6, GameVersion.Crash1BetaMAR08)] 5 | [EntryType(6, GameVersion.Crash1BetaMAY11)] 6 | public sealed class T6EntryLoader : EntryLoader 7 | { 8 | public override Entry Load(byte[][] items, int eid) 9 | { 10 | ArgumentNullException.ThrowIfNull(items); 11 | if (items.Length != 1) 12 | { 13 | ErrorManager.SignalError("T6Entry: Wrong number of items"); 14 | } 15 | return new T6Entry(items[0], eid); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Texture/TextureChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class TextureChunk : Chunk, IEntry 4 | { 5 | public TextureChunk(byte[] data) 6 | { 7 | Data = data ?? throw new ArgumentNullException(nameof(data)); 8 | } 9 | 10 | public override string Title => $"Texture Chunk {ChunkId} ({EName})"; 11 | public override string ImageKey => "Painting"; 12 | 13 | public override short Type => 1; 14 | public int EID 15 | { 16 | get => BitConv.FromInt32(Data, 4); 17 | set => BitConv.ToInt32(Data, 4, value); 18 | } 19 | public string EName => Entry.EIDToEName(EID); 20 | public int HashKey => EID >> 15 & 0xFF; 21 | public byte[] Data { get; } 22 | 23 | public override UnprocessedChunk Unprocess() 24 | { 25 | return new UnprocessedChunk(Data); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Texture/TextureChunkLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [ChunkType(1)] 4 | public sealed class TextureChunkLoader : ChunkLoader 5 | { 6 | public override Chunk Load(byte[] data) 7 | { 8 | ArgumentNullException.ThrowIfNull(data); 9 | return new TextureChunk(data); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Wavebank/WavebankChunk.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class WavebankChunk : EntryChunk 4 | { 5 | public WavebankChunk() 6 | { 7 | } 8 | 9 | public WavebankChunk(IEnumerable entries) : base(entries) 10 | { 11 | } 12 | 13 | public override string Title => $"Wavebank Chunk {ChunkId}"; 14 | public override string ImageKey => "MusicNoteRed"; 15 | 16 | public override short Type => 4; 17 | public override int Alignment => 16; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Wavebank/WavebankChunkLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [ChunkType(4)] 4 | public sealed class WavebankChunkLoader : EntryChunkLoader 5 | { 6 | public override EntryChunk Load(Entry[] entries) 7 | { 8 | ArgumentNullException.ThrowIfNull(entries); 9 | return new WavebankChunk(entries); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Wavebank/WavebankEntry.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class WavebankEntry : Entry 4 | { 5 | public const int MaxSampleLines = 4089; 6 | 7 | public WavebankEntry(int id, SampleSet samples, int eid) : base(eid) 8 | { 9 | ID = id; 10 | Samples = samples ?? throw new ArgumentNullException(nameof(samples)); 11 | } 12 | 13 | public override string Title => $"Wavebank ({EName})"; 14 | public override string ImageKey => "MusicNoteYellow"; 15 | 16 | public override int Type => 14; 17 | public int ID { get; } 18 | public SampleSet Samples { get; } 19 | 20 | public override UnprocessedEntry Unprocess() 21 | { 22 | byte[] info = new byte[8]; 23 | byte[] data = Samples.Save(); 24 | BitConv.ToInt32(info, 0, ID); 25 | BitConv.ToInt32(info, 4, data.Length); 26 | byte[][] items = new byte[2][]; 27 | items[0] = info; 28 | items[1] = data; 29 | return new UnprocessedEntry(items, EID, Type); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Wavebank/WavebankEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(14, GameVersion.Crash1BetaMAR08)] 4 | [EntryType(14, GameVersion.Crash1BetaMAY11)] 5 | [EntryType(14, GameVersion.Crash1)] 6 | [EntryType(14, GameVersion.Crash2)] 7 | [EntryType(14, GameVersion.Crash3)] 8 | public sealed class WavebankEntryLoader : EntryLoader 9 | { 10 | public override Entry Load(byte[][] items, int eid) 11 | { 12 | ArgumentNullException.ThrowIfNull(items); 13 | if (items.Length != 2) 14 | { 15 | ErrorManager.SignalError("WavebankEntry: Wrong number of items"); 16 | } 17 | if (items[0].Length != 8) 18 | { 19 | ErrorManager.SignalError("WavebankEntry: First item length is wrong"); 20 | } 21 | int id = BitConv.FromInt32(items[0], 0); 22 | int length = BitConv.FromInt32(items[0], 4); 23 | if (id < 0 || id > 6) 24 | { 25 | ErrorManager.SignalIgnorableError("WavebankEntry: ID is invalid"); 26 | } 27 | if (length != items[1].Length) 28 | { 29 | ErrorManager.SignalIgnorableError("WavebankEntry: Length field mismatch"); 30 | } 31 | return new WavebankEntry(id, SampleSet.Load(items[1]), eid); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityID.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct EntityID 4 | { 5 | public EntityID(int id) 6 | { 7 | ID = id; 8 | AlternateID = null; 9 | } 10 | 11 | public EntityID(int id, int? alternateid) 12 | { 13 | ID = id; 14 | AlternateID = alternateid; 15 | } 16 | 17 | public int ID { get; } 18 | public int? AlternateID { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityInt32PropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntityPropertyType(19)] 4 | public sealed class EntityInt32PropertyLoader : EntityBasicPropertyLoader 5 | { 6 | protected override byte ElementSize => 4; 7 | 8 | protected override int LoadElement(byte[] data) 9 | { 10 | return BitConv.FromInt32(data, 0); 11 | } 12 | 13 | protected override EntityProperty Load(IEnumerable> rows) 14 | { 15 | return new EntityInt32Property(rows); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityPosition.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public readonly struct EntityPosition 4 | { 5 | public EntityPosition(short x, short y, short z) 6 | { 7 | X = x; 8 | Y = y; 9 | Z = z; 10 | } 11 | 12 | public EntityPosition(Position p) 13 | { 14 | X = (short)p.X; 15 | Y = (short)p.Y; 16 | Z = (short)p.Z; 17 | } 18 | 19 | public short X { get; } 20 | public short Y { get; } 21 | public short Z { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityPositionProperty.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class EntityPositionProperty : EntityBasicProperty 4 | { 5 | public EntityPositionProperty() 6 | { 7 | } 8 | 9 | public EntityPositionProperty(IEnumerable> rows) : base(rows) 10 | { 11 | } 12 | 13 | public override byte Type => 6; 14 | public override byte ElementSize => 6; 15 | 16 | protected override void SaveElement(byte[] data, EntityPosition value) 17 | { 18 | BitConv.ToInt16(data, 0, value.X); 19 | BitConv.ToInt16(data, 2, value.Y); 20 | BitConv.ToInt16(data, 4, value.Z); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityPositionPropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntityPropertyType(6)] 4 | public sealed class EntityPositionPropertyLoader : EntityBasicPropertyLoader 5 | { 6 | protected override byte ElementSize => 6; 7 | 8 | protected override EntityPosition LoadElement(byte[] data) 9 | { 10 | short x = BitConv.FromInt16(data, 0); 11 | short y = BitConv.FromInt16(data, 2); 12 | short z = BitConv.FromInt16(data, 4); 13 | return new EntityPosition(x, y, z); 14 | } 15 | 16 | protected override EntityProperty Load(IEnumerable> rows) 17 | { 18 | return new EntityPositionProperty(rows); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityPropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public abstract class EntityPropertyLoader 4 | { 5 | public abstract EntityProperty Load(byte elementsize, short unknown, bool issparse, bool hasmetavalues, byte[] data); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityPropertyRow.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class EntityPropertyRow 4 | { 5 | private List values; 6 | 7 | public EntityPropertyRow() 8 | { 9 | MetaValue = null; 10 | values = new List(); 11 | } 12 | 13 | public short? MetaValue { get; set; } 14 | public IList Values => values; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityPropertyTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [AttributeUsage(AttributeTargets.Class)] 4 | public sealed class EntityPropertyTypeAttribute : Attribute 5 | { 6 | public EntityPropertyTypeAttribute(byte type) 7 | { 8 | Type = type; 9 | } 10 | 11 | public byte Type { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntitySetting.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct EntitySetting 4 | { 5 | public EntitySetting(byte valuea, int valueb) 6 | { 7 | if (valueb < -8388608 || valueb > 8388607) 8 | throw new ArgumentOutOfRangeException(nameof(valueb)); 9 | Value = valuea | (valueb << 8); 10 | } 11 | 12 | public EntitySetting(int value) 13 | { 14 | Value = value; 15 | } 16 | 17 | public byte ValueA => (byte)(Value); 18 | public int ValueB => (Value & -256) >> 8; 19 | public int Value { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntitySettingProperty.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class EntitySettingProperty : EntityBasicProperty 4 | { 5 | public EntitySettingProperty() 6 | { 7 | } 8 | 9 | public EntitySettingProperty(IEnumerable> rows) : base(rows) 10 | { 11 | } 12 | 13 | public override byte Type => 5; 14 | public override byte ElementSize => 4; 15 | 16 | protected override void SaveElement(byte[] data, EntitySetting value) 17 | { 18 | BitConv.ToInt32(data, 0, value.Value); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntitySettingPropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntityPropertyType(5)] 4 | public sealed class EntitySettingPropertyLoader : EntityBasicPropertyLoader 5 | { 6 | protected override byte ElementSize => 4; 7 | 8 | protected override EntitySetting LoadElement(byte[] data) 9 | { 10 | return new EntitySetting(BitConv.FromInt32(data, 0)); 11 | } 12 | 13 | protected override EntityProperty Load(IEnumerable> rows) 14 | { 15 | return new EntitySettingProperty(rows); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityT4Property.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class EntityT4Property : EntityBasicProperty 4 | { 5 | public EntityT4Property() 6 | { 7 | } 8 | 9 | public EntityT4Property(IEnumerable> rows) : base(rows) 10 | { 11 | } 12 | 13 | public override byte Type => 4; 14 | public override byte ElementSize => 4; 15 | 16 | protected override void SaveElement(byte[] data, int value) 17 | { 18 | BitConv.ToInt32(data, 0, value); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityT4PropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntityPropertyType(4)] 4 | public sealed class EntityT4PropertyLoader : EntityBasicPropertyLoader 5 | { 6 | protected override byte ElementSize => 4; 7 | 8 | protected override int LoadElement(byte[] data) 9 | { 10 | return BitConv.FromInt32(data, 0); 11 | } 12 | 13 | protected override EntityProperty Load(IEnumerable> rows) 14 | { 15 | return new EntityT4Property(rows); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityUInt32Property.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class EntityUInt32Property : EntityBasicProperty 4 | { 5 | public EntityUInt32Property() 6 | { 7 | } 8 | 9 | public EntityUInt32Property(IEnumerable> rows) : base(rows) 10 | { 11 | } 12 | 13 | public override byte Type => 3; 14 | public override byte ElementSize => 4; 15 | 16 | protected override void SaveElement(byte[] data, uint value) 17 | { 18 | BitConv.ToInt32(data, 0, (int)value); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityUInt32PropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntityPropertyType(3)] 4 | public sealed class EntityUInt32PropertyLoader : EntityBasicPropertyLoader 5 | { 6 | protected override byte ElementSize => 4; 7 | 8 | protected override uint LoadElement(byte[] data) 9 | { 10 | return (uint)BitConv.FromInt32(data, 0); 11 | } 12 | 13 | protected override EntityProperty Load(IEnumerable> rows) 14 | { 15 | return new EntityUInt32Property(rows); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityUInt8PropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntityPropertyType(1)] 4 | public sealed class EntityUInt8PropertyLoader : EntityBasicPropertyLoader 5 | { 6 | protected override byte ElementSize => 1; 7 | 8 | protected override byte LoadElement(byte[] data) 9 | { 10 | return data[0]; 11 | } 12 | 13 | protected override EntityProperty Load(IEnumerable> rows) 14 | { 15 | return new EntityUInt8Property(rows); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityUnknownProperty.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class EntityUnknownProperty : EntityProperty 4 | { 5 | private readonly byte type; 6 | private readonly byte elementsize; 7 | private readonly short unknown; 8 | private readonly bool issparse; 9 | private readonly bool hasmetavalues; 10 | 11 | public EntityUnknownProperty(byte type, byte elementsize, short unknown, bool issparse, bool hasmetavalues, byte[] data) 12 | { 13 | this.type = type; 14 | this.elementsize = elementsize; 15 | this.unknown = unknown; 16 | this.issparse = issparse; 17 | this.hasmetavalues = hasmetavalues; 18 | Data = data; 19 | } 20 | 21 | public override byte Type => type; 22 | public override byte ElementSize => elementsize; 23 | public override short RowCount => unknown; 24 | public override bool IsSparse => issparse; 25 | public override bool HasMetaValues => hasmetavalues; 26 | public byte[] Data { get; } 27 | 28 | public override byte[] Save() 29 | { 30 | return Data; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityVictim.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct EntityVictim 4 | { 5 | public EntityVictim(short victimid) 6 | { 7 | VictimID = victimid; 8 | } 9 | 10 | public short VictimID { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityVictimProperty.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public sealed class EntityVictimProperty : EntityBasicProperty 4 | { 5 | public EntityVictimProperty() 6 | { 7 | } 8 | 9 | public EntityVictimProperty(IEnumerable> rows) : base(rows) 10 | { 11 | } 12 | 13 | public override byte Type => 18; 14 | public override byte ElementSize => 2; 15 | 16 | protected override void SaveElement(byte[] data, EntityVictim value) 17 | { 18 | BitConv.ToInt16(data, 0, value.VictimID); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/EntityVictimPropertyLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntityPropertyType(18)] 4 | public sealed class EntityVictimPropertyLoader : EntityBasicPropertyLoader 5 | { 6 | protected override byte ElementSize => 2; 7 | 8 | protected override EntityVictim LoadElement(byte[] data) 9 | { 10 | short victimid = BitConv.FromInt16(data, 0); 11 | return new EntityVictim(victimid); 12 | } 13 | 14 | protected override EntityProperty Load(IEnumerable> rows) 15 | { 16 | return new EntityVictimProperty(rows); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/OldCameraNeighbor.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct OldCameraNeighbor 4 | { 5 | public OldCameraNeighbor(byte linktype, byte zoneindex, byte cameraindex, byte flag) 6 | { 7 | LinkType = linktype; 8 | ZoneIndex = zoneindex; 9 | CameraIndex = cameraindex; 10 | Flag = flag; 11 | } 12 | 13 | public byte LinkType { get; set; } 14 | public byte ZoneIndex { get; set; } 15 | public byte CameraIndex { get; set; } 16 | public byte Flag { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/OldCameraPosition.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public readonly struct OldCameraPosition 4 | { 5 | public OldCameraPosition(short x, short y, short z, short xrot, short yrot, short zrot) 6 | { 7 | X = x; 8 | Y = y; 9 | Z = z; 10 | XRot = xrot; 11 | YRot = yrot; 12 | ZRot = zrot; 13 | } 14 | 15 | public short X { get; } 16 | public short Y { get; } 17 | public short Z { get; } 18 | public short XRot { get; } 19 | public short YRot { get; } 20 | public short ZRot { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/OldZoneEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(7, GameVersion.Crash1BetaMAR08)] 4 | [EntryType(7, GameVersion.Crash1BetaMAY11)] 5 | [EntryType(7, GameVersion.Crash1)] 6 | public sealed class OldZoneEntryLoader : EntryLoader 7 | { 8 | public override Entry Load(byte[][] items, int eid) 9 | { 10 | ArgumentNullException.ThrowIfNull(items); 11 | if (items.Length < 2) 12 | { 13 | ErrorManager.SignalError("OldZoneEntry: Wrong number of items"); 14 | } 15 | byte[] header = items[0]; 16 | byte[] layout = items[1]; 17 | int camcount = BitConv.FromInt32(header, 0x208); 18 | OldCamera[] cameras = new OldCamera[camcount]; 19 | for (int i = 2; i < 2 + camcount; i++) 20 | { 21 | cameras[i - 2] = OldCamera.Load(items[i]); 22 | } 23 | int entitycount = BitConv.FromInt32(header, 0x20C); 24 | OldEntity[] entities = new OldEntity[entitycount]; 25 | for (int i = 2 + camcount; i < 2 + camcount + entitycount; i++) 26 | { 27 | entities[i - 2 - camcount] = OldEntity.Load(items[i]); 28 | } 29 | return new OldZoneEntry(header, layout, cameras, entities, eid); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/ProtoEntityPosition.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public struct ProtoEntityPosition 4 | { 5 | public ProtoEntityPosition(sbyte x, sbyte y, sbyte z) 6 | { 7 | X = x; 8 | Y = y; 9 | Z = z; 10 | } 11 | 12 | public sbyte X { get; } 13 | public sbyte Y { get; } 14 | public sbyte Z { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/ProtoZoneEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(7, GameVersion.Crash1Beta1995)] 4 | public sealed class ProtoZoneEntryLoader : EntryLoader 5 | { 6 | public override Entry Load(byte[][] items, int eid) 7 | { 8 | if (items.Length < 2) 9 | { 10 | ErrorManager.SignalError("ProtoZoneEntry: Wrong number of items"); 11 | } 12 | byte[] header = items[0]; 13 | byte[] layout = items[1]; 14 | int camcount = BitConv.FromInt32(header, 520); 15 | OldCamera[] cameras = new OldCamera[camcount]; 16 | for (int i = 2; i < 2 + camcount; i++) 17 | { 18 | cameras[i - 2] = OldCamera.Load(items[i]); 19 | } 20 | ProtoEntity[] entities = new ProtoEntity[items.Length - 2 - camcount]; 21 | for (int i = 2 + camcount; i < items.Length; i++) 22 | { 23 | entities[i - 2 - camcount] = ProtoEntity.Load(items[i]); 24 | } 25 | return new ProtoZoneEntry(header, layout, cameras, entities, eid); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Crash/Formats/Crash Formats/Zone/ZoneEntryLoader.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [EntryType(7, GameVersion.Crash2)] 4 | [EntryType(7, GameVersion.Crash3)] 5 | public sealed class ZoneEntryLoader : EntryLoader 6 | { 7 | public override Entry Load(byte[][] items, int eid) 8 | { 9 | if (items.Length < 2) 10 | { 11 | ErrorManager.SignalError("ZoneEntry: Wrong number of items"); 12 | } 13 | byte[] header = items[0]; 14 | byte[] layout = items[1]; 15 | Entity[] entities = new Entity[items.Length - 2]; 16 | for (int i = 2; i < items.Length; i++) 17 | { 18 | entities[i - 2] = Entity.Load(items[i]); 19 | } 20 | return new ZoneEntry(header, layout, entities, eid); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Crash/Formats/PSX Formats/ADPCM/SampleLineFlags.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | [Flags] 4 | public enum SampleLineFlags : byte 5 | { 6 | None = 0, 7 | LoopEnd = 1, 8 | Unknown = 2, 9 | LoopStart = 4 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Crash/Formats/PSX Formats/SeqExporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | 4 | public sealed class SeqExporter : Exporter 5 | { 6 | 7 | public override string Text => "PlayStation SEQ"; 8 | 9 | public override string[] FileFilters => new string[] { 10 | "PlayStation SEQ files (*.seq)|*.seq;*.SEQ" 11 | }; 12 | 13 | public override bool Export(IUserInterface ui, out ReadOnlySpan buf, SEQ res) 14 | { 15 | ArgumentNullException.ThrowIfNull(ui); 16 | ArgumentNullException.ThrowIfNull(res); 17 | 18 | buf = new ReadOnlySpan(res.Save()); 19 | return true; 20 | } 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Formats/PSX Formats/SeqImporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | 4 | public sealed class SeqImporter : Importer 5 | { 6 | 7 | public override string[] FileFilters => new string[] { 8 | "PlayStation SEQ files (*.seq)|*.seq;*.SEQ" 9 | }; 10 | 11 | public override bool Import(IUserInterface ui, ReadOnlySpan buf, out SEQ res) 12 | { 13 | ArgumentNullException.ThrowIfNull(ui); 14 | 15 | res = SEQ.Load(buf.ToArray()); 16 | return true; 17 | } 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Formats/PSX Formats/SeqToMidiExporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | 4 | public sealed class SeqToMidiExporter : Exporter 5 | { 6 | 7 | public override string Text => "Standard MIDI"; 8 | 9 | public override string[] FileFilters => new string[] { 10 | "Standard MIDI files (*.mid, *.midi)|*.mid;*.MID;*.midi;*.MIDI" 11 | }; 12 | 13 | public override bool Export(IUserInterface ui, out ReadOnlySpan buf, SEQ res) 14 | { 15 | ArgumentNullException.ThrowIfNull(ui); 16 | ArgumentNullException.ThrowIfNull(res); 17 | 18 | buf = new ReadOnlySpan(res.ToMIDI()); 19 | return true; 20 | } 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Formats/PSX Formats/VAB/VhExporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | 4 | public sealed class VhExporter : Exporter 5 | { 6 | 7 | public override string Text => "PlayStation VH"; 8 | 9 | public override string[] FileFilters => new string[] { 10 | "PlayStation VAB headers (*.vh)|*.vh;*.VH" 11 | }; 12 | 13 | public override bool Export(IUserInterface ui, out ReadOnlySpan buf, VH res) 14 | { 15 | ArgumentNullException.ThrowIfNull(ui); 16 | ArgumentNullException.ThrowIfNull(res); 17 | 18 | buf = new ReadOnlySpan(res.Save()); 19 | return true; 20 | } 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Crash/Formats/PSX Formats/VAB/VhImporter.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | 4 | public sealed class VhImporter : Importer 5 | { 6 | 7 | public override string[] FileFilters => new string[] { 8 | "PlayStation VAB headers (*.vh)|*.vh;*.VH" 9 | }; 10 | 11 | public override bool Import(IUserInterface ui, ReadOnlySpan buf, out VH res) 12 | { 13 | ArgumentNullException.ThrowIfNull(ui); 14 | 15 | res = VH.Load(buf.ToArray()); 16 | return true; 17 | } 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Crash/Utility/ADPCMConv.cs: -------------------------------------------------------------------------------- 1 | // Based on code by bITmASTER and nextvolume 2 | // http://psxsdk.googlecode.com/svn-history/r13/trunk/tools/vag2wav.c 3 | namespace CrashEdit.Crash 4 | { 5 | public static class ADPCMConv 6 | { 7 | private static readonly int[] f0 = { 0, 60, 115, 98, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 8 | private static readonly int[] f1 = { 0, 0, -52, -55, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 9 | 10 | public static short FromADPCM(int sample, int factor, int predict, ref double s0, ref double s1) 11 | { 12 | if ((sample & 0xF) != sample) 13 | throw new ArgumentOutOfRangeException(nameof(sample)); 14 | if ((factor & 0xF) != factor) 15 | throw new ArgumentOutOfRangeException(nameof(factor)); 16 | if ((predict & 0xF) != predict) 17 | throw new ArgumentOutOfRangeException(nameof(predict)); 18 | if (predict >= 16) 19 | throw new ArgumentOutOfRangeException(nameof(predict)); 20 | sample <<= 12; 21 | sample = (short)sample; // Sign extend 22 | sample >>= factor; 23 | double value = sample; 24 | value += s0 * f0[predict] / 64; 25 | value += s1 * f1[predict] / 64; 26 | s1 = s0; 27 | s0 = value; 28 | return (short)Math.Round(value); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Crash/Utility/Aligner.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public static class Aligner 4 | { 5 | public static int Align(int position, int alignment) 6 | { 7 | Align(ref position, alignment); 8 | return position; 9 | } 10 | 11 | public static void Align(ref int position, int alignment) 12 | { 13 | ArgumentOutOfRangeException.ThrowIfNegative(position); 14 | ArgumentOutOfRangeException.ThrowIfNegativeOrZero(alignment); 15 | if (position > 0) position += -(((position - 1) % alignment) + 1) + alignment; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Utility/Endianness.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public enum Endianness 4 | { 5 | LittleEndian, 6 | BigEndian 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Crash/Utility/IPosition.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public interface IPosition 4 | { 5 | float X { get; } 6 | float Y { get; } 7 | float Z { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Crash/Utility/ListExt.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public static class ListExt 4 | { 5 | public static IList Swap(this IList list, int a, int b) 6 | { 7 | T temp = list[a]; 8 | list[a] = list[b]; 9 | list[b] = temp; 10 | return list; 11 | } 12 | 13 | public static void RemoveLast(this IList list) 14 | { 15 | list.RemoveAt(list.Count - 1); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Crash/Utility/MIDIConv.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public static class MIDIConv 4 | { 5 | public static int From3BE(byte[] str, int offset) 6 | { 7 | ArgumentNullException.ThrowIfNull(str); 8 | if (offset < 0) 9 | throw new ArgumentOutOfRangeException(nameof(offset)); 10 | if (offset + 3 > str.Length) 11 | throw new ArgumentOutOfRangeException(nameof(offset)); 12 | int result = 0; 13 | result |= str[offset + 0] << 8 * 2; 14 | result |= str[offset + 1] << 8 * 1; 15 | result |= str[offset + 2] << 8 * 0; 16 | return result; 17 | } 18 | 19 | public static void To3BE(byte[] str, int offset, int value) 20 | { 21 | ArgumentNullException.ThrowIfNull(str); 22 | if (offset < 0) 23 | throw new ArgumentOutOfRangeException(nameof(offset)); 24 | if (offset + 3 > str.Length) 25 | throw new ArgumentOutOfRangeException(nameof(offset)); 26 | if ((value & 0xFFFFFF) != value) 27 | throw new ArgumentOutOfRangeException(nameof(value)); 28 | str[offset + 0] = (byte)((value >> 8 * 2) & 0xFF); 29 | str[offset + 1] = (byte)((value >> 8 * 1) & 0xFF); 30 | str[offset + 2] = (byte)((value >> 8 * 0) & 0xFF); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Crash/Utility/Position.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public readonly struct Position : IPosition 4 | { 5 | public static readonly Position Unit = new Position(1, 1, 1); 6 | 7 | public Position(float x, float y, float z) 8 | { 9 | X = x; 10 | Y = y; 11 | Z = z; 12 | } 13 | 14 | public Position(IPosition pos) 15 | { 16 | X = pos.X; 17 | Y = pos.Y; 18 | Z = pos.Z; 19 | } 20 | 21 | public float X { get; } 22 | public float Y { get; } 23 | public float Z { get; } 24 | 25 | public static Position operator +(Position a, Position b) => new Position(a.X + b.X, a.Y + b.Y, a.Z + b.Z); 26 | public static Position operator -(Position a, Position b) => new Position(a.X - b.X, a.Y - b.Y, a.Z - b.Z); 27 | public static Position operator *(Position a, Position b) => new Position(a.X * b.X, a.Y * b.Y, a.Z * b.Z); 28 | public static Position operator /(Position a, Position b) => new Position(a.X / b.X, a.Y / b.Y, a.Z / b.Z); 29 | public static Position operator *(Position a, float b) => new Position(a.X * b, a.Y * b, a.Z * b); 30 | public static Position operator *(float b, Position a) => new Position(a.X * b, a.Y * b, a.Z * b); 31 | public static Position operator /(Position a, float b) => new Position(a.X / b, a.Y / b, a.Z / b); 32 | public static Position operator /(float b, Position a) => new Position(a.X / b, a.Y / b, a.Z / b); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Crash/Utility/StringExt.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public static class StringExt 4 | { 5 | public static int AmountOf(this string str, char c) 6 | { 7 | int count = 0; 8 | foreach (char str_c in str) 9 | if (str_c == c) ++count; 10 | return count; 11 | } 12 | 13 | public static string Reverse(this string str) 14 | { 15 | var arr = str.ToCharArray(); 16 | System.Array.Reverse(arr); 17 | return new string(arr); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Crash/Utility/WaveConv.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.Crash 2 | { 3 | public static class WaveConv 4 | { 5 | public static RIFF ToWave(byte[] data, int samplerate) 6 | { 7 | ArgumentNullException.ThrowIfNull(data); 8 | byte[] format = new byte[16]; 9 | BitConv.ToInt16(format, 0, 1); 10 | BitConv.ToInt16(format, 2, 1); 11 | BitConv.ToInt32(format, 4, samplerate); 12 | BitConv.ToInt32(format, 8, samplerate * 2); 13 | BitConv.ToInt16(format, 12, 2); 14 | BitConv.ToInt16(format, 14, 16); 15 | RIFF wave = new RIFF("WAVE"); 16 | wave.Items.Add(new RIFFData("fmt ", format)); 17 | wave.Items.Add(new RIFFData("data", data)); 18 | return wave; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Animation/AnimationEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(AnimationEntry))] 6 | public sealed class AnimationEntryController : EntryController 7 | { 8 | public AnimationEntryController(AnimationEntry animationentry, SubcontrollerGroup parentGroup) : base(animationentry, parentGroup) 9 | { 10 | AnimationEntry = animationentry; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new AnimationEntryViewer(GetNSF(), Entry.EID); 18 | } 19 | 20 | public AnimationEntry AnimationEntry { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Animation/ColoredAnimationEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(ColoredAnimationEntry))] 6 | public sealed class ColoredAnimationEntryController : EntryController 7 | { 8 | public ColoredAnimationEntryController(ColoredAnimationEntry coloredanimationentry, SubcontrollerGroup parentGroup) 9 | : base(coloredanimationentry, parentGroup) 10 | { 11 | ColoredAnimationEntry = coloredanimationentry; 12 | } 13 | 14 | public override bool EditorAvailable => true; 15 | 16 | public override Control CreateEditor() 17 | { 18 | return new OldAnimationEntryViewer(GetNSF(), Entry.EID); 19 | } 20 | 21 | public ColoredAnimationEntry ColoredAnimationEntry { get; } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Animation/FrameController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(Frame))] 6 | public sealed class FrameController : LegacyController 7 | { 8 | public FrameController(Frame frame, SubcontrollerGroup parentGroup) : base(parentGroup, frame) 9 | { 10 | Frame = frame; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new AnimationEntryViewer(GetNSF(), AnimationEntryController.AnimationEntry.EID, AnimationEntryController.AnimationEntry.Frames.IndexOf(Frame)); 18 | } 19 | 20 | public AnimationEntryController AnimationEntryController => (AnimationEntryController)Modern.Parent.Legacy; 21 | public Frame Frame { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Animation/OldAnimationEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(OldAnimationEntry))] 6 | public sealed class OldAnimationEntryController : EntryController 7 | { 8 | public OldAnimationEntryController(OldAnimationEntry oldanimationentry, SubcontrollerGroup parentGroup) : base(oldanimationentry, parentGroup) 9 | { 10 | OldAnimationEntry = oldanimationentry; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new OldAnimationEntryViewer(GetNSF(), Entry.EID); 18 | } 19 | 20 | public OldAnimationEntry OldAnimationEntry { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Base/Chunk/ChunkController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public abstract class ChunkController : LegacyController 6 | { 7 | public ChunkController(Chunk chunk, SubcontrollerGroup parentGroup) : base(parentGroup, chunk) 8 | { 9 | Chunk = chunk; 10 | if (!(this is UnprocessedChunkController)) 11 | { 12 | AddMenu(CrashUI.Properties.Resources.ChunkController_AcDeprocess, Menu_Unprocess_Chunk); 13 | } 14 | } 15 | 16 | protected NSFController NSFController => (NSFController)Modern.Parent.Legacy; 17 | public Chunk Chunk { get; } 18 | 19 | private void Menu_Unprocess_Chunk() 20 | { 21 | int index = NSFController.NSF.Chunks.IndexOf(Chunk); 22 | UnprocessedChunk unprocessedchunk = Chunk.Unprocess(); 23 | NSFController.NSF.Chunks[index] = unprocessedchunk; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Controller.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public abstract class LegacyController : CrashEdit.LegacyController 6 | { 7 | public LegacyController(SubcontrollerGroup parentGroup, object resource) : base(parentGroup, resource) { } 8 | 9 | protected void AddMenu(string text, ControllerMenuDelegate proc) 10 | { 11 | LegacyVerbs.Add(new LegacyVerb(text, new Action(proc))); 12 | } 13 | 14 | protected void AddMenuSeparator() 15 | { 16 | // FIXME 17 | } 18 | 19 | public GameVersion GameVersion => 20 | (Modern.Root.Resource as LevelWorkspace)?.GameVersion ?? GameVersion.None; 21 | 22 | public NSF GetNSF() 23 | { 24 | return (Modern.Root.Resource as LevelWorkspace)?.NSF; 25 | } 26 | 27 | public T? GetEntry(int eid) where T : class, IEntry 28 | { 29 | return (Modern.Root?.Resource as LevelWorkspace)?.NSF?.GetEntry(eid); 30 | } 31 | 32 | public IEnumerable GetEntries() where T : class, IEntry 33 | { 34 | return (Modern.Root.Resource as LevelWorkspace)?.NSF?.GetEntries(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/ControllerMenuDelegate.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | public delegate void ControllerMenuDelegate(); 4 | } 5 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Model/ModelEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(ModelEntry))] 6 | public sealed class ModelEntryController : EntryController 7 | { 8 | public ModelEntryController(ModelEntry modelentry, SubcontrollerGroup parentGroup) : base(modelentry, parentGroup) 9 | { 10 | ModelEntry = modelentry; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | if (ModelEntry.Positions == null) 18 | return new Label { Text = string.Format("Polygon count: {0}\nVertex count: {1}", ModelEntry.PolyCount, ModelEntry.VertexCount), TextAlign = ContentAlignment.MiddleCenter }; 19 | else 20 | { 21 | int totalbits = ModelEntry.Positions.Count * 8 * 3; 22 | int bits = 0; 23 | foreach (ModelPosition pos in ModelEntry.Positions) 24 | { 25 | bits += 1 + pos.XBits; 26 | bits += 1 + pos.YBits; 27 | bits += 1 + pos.ZBits; 28 | } 29 | return new Label { Text = string.Format("Polygon count: {0}\nVertex count: {1}\nCompression ratio: {2:P1} ({3}/{4})", ModelEntry.PolyCount, ModelEntry.VertexCount, (float)bits / totalbits, bits, totalbits), TextAlign = ContentAlignment.MiddleCenter }; 30 | } 31 | } 32 | 33 | public ModelEntry ModelEntry { get; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Model/OldModelEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(OldModelEntry))] 6 | public sealed class OldModelEntryController : EntryController 7 | { 8 | public OldModelEntryController(OldModelEntry oldmodelentry, SubcontrollerGroup parentGroup) : base(oldmodelentry, parentGroup) 9 | { 10 | OldModelEntry = oldmodelentry; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new Label { Text = string.Format("Polygon count: {0}", BitConv.FromInt32(OldModelEntry.Info, 0)), TextAlign = ContentAlignment.MiddleCenter }; 18 | } 19 | 20 | public OldModelEntry OldModelEntry { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Mystery/MysteryUniItemEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(MysteryUniItemEntry))] 6 | public class MysteryUniItemEntryController : EntryController 7 | { 8 | public MysteryUniItemEntryController(MysteryUniItemEntry mysteryentry, SubcontrollerGroup parentGroup) : base(mysteryentry, parentGroup) 9 | { 10 | MysteryEntry = mysteryentry; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new MysteryBox(MysteryEntry.Data); 18 | } 19 | 20 | public MysteryUniItemEntry MysteryEntry { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Palette/PaletteEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(PaletteEntry))] 6 | public sealed class PaletteEntryController : EntryController 7 | { 8 | public PaletteEntryController(PaletteEntry paletteentry, SubcontrollerGroup parentGroup) : base(paletteentry, parentGroup) 9 | { 10 | PaletteEntry = paletteentry; 11 | } 12 | 13 | public override bool EditorAvailable => Type.GetType("Mono.Runtime") == null; 14 | 15 | public override Control CreateEditor() 16 | { 17 | // Hack for Mono so it doesn't crash. 18 | if (Type.GetType("Mono.Runtime") != null) 19 | return base.CreateEditor(); 20 | return new PaletteEntryBox(PaletteEntry); 21 | } 22 | 23 | public PaletteEntry PaletteEntry { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/SLST/OldSLSTDeltaController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(OldSLSTDelta))] 6 | public sealed class OldSLSTDeltaController : LegacyController 7 | { 8 | public OldSLSTDeltaController(OldSLSTDelta oldslstdelta, SubcontrollerGroup parentGroup) : base(parentGroup, oldslstdelta) 9 | { 10 | OldSLSTDelta = oldslstdelta; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new OldSLSTDeltaBox(OldSLSTDelta); 18 | } 19 | 20 | public OldSLSTDelta OldSLSTDelta { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/SLST/OldSLSTSourceController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(OldSLSTSource))] 6 | public sealed class OldSLSTSourceController : LegacyController 7 | { 8 | public OldSLSTSourceController(OldSLSTSource oldslstsource, SubcontrollerGroup parentGroup) : base(parentGroup, oldslstsource) 9 | { 10 | OldSLSTSource = oldslstsource; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new OldSLSTSourceBox(OldSLSTSource); 18 | } 19 | 20 | public OldSLSTSource OldSLSTSource { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/SLST/SLSTDeltaController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(SLSTDelta))] 6 | public sealed class SLSTDeltaController : LegacyController 7 | { 8 | public SLSTDeltaController(SLSTDelta slstdelta, SubcontrollerGroup parentGroup) : base(parentGroup, slstdelta) 9 | { 10 | SLSTDelta = slstdelta; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new SLSTDeltaBox(SLSTDelta); 18 | } 19 | 20 | public SLSTDelta SLSTDelta { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/SLST/SLSTSourceController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(SLSTSource))] 6 | public sealed class SLSTSourceController : LegacyController 7 | { 8 | public SLSTSourceController(SLSTSource slstsource, SubcontrollerGroup parentGroup) : base(parentGroup, slstsource) 9 | { 10 | SLSTSource = slstsource; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new SLSTSourceBox(SLSTSource); 18 | } 19 | 20 | public SLSTSource SLSTSource { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Sound/SoundEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(SoundEntry))] 6 | public sealed class SoundEntryController : EntryController 7 | { 8 | public SoundEntryController(SoundEntry soundentry, SubcontrollerGroup parentGroup) : base(soundentry, parentGroup) 9 | { 10 | SoundEntry = soundentry; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new SoundBox(SoundEntry); 18 | } 19 | 20 | public SoundEntry SoundEntry { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Speech/SpeechEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(SpeechEntry))] 6 | public sealed class SpeechEntryController : EntryController 7 | { 8 | public SpeechEntryController(SpeechEntry speechentry, SubcontrollerGroup parentGroup) : base(speechentry, parentGroup) 9 | { 10 | SpeechEntry = speechentry; 11 | } 12 | 13 | public override bool EditorAvailable => true; 14 | 15 | public override Control CreateEditor() 16 | { 17 | return new SoundBox(SpeechEntry); 18 | } 19 | 20 | public SpeechEntry SpeechEntry { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Unprocessed/UnprocessedChunkController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(UnprocessedChunk))] 6 | public sealed class UnprocessedChunkController : ChunkController 7 | { 8 | public UnprocessedChunkController(UnprocessedChunk unprocessedchunk, SubcontrollerGroup parentGroup) : base(unprocessedchunk, parentGroup) 9 | { 10 | UnprocessedChunk = unprocessedchunk; 11 | AddMenu(CrashUI.Properties.Resources.UnprocessedChunkController_AcProcess, Menu_Process_Chunk); 12 | } 13 | 14 | public UnprocessedChunk UnprocessedChunk { get; } 15 | 16 | private void Menu_Process_Chunk() 17 | { 18 | Chunk processedchunk; 19 | try 20 | { 21 | processedchunk = UnprocessedChunk.Process(); 22 | } 23 | catch (LoadAbortedException) 24 | { 25 | return; 26 | } 27 | int index = GetNSF().Chunks.IndexOf(UnprocessedChunk); 28 | GetNSF().Chunks[index] = processedchunk; 29 | if (processedchunk is EntryChunk) 30 | { 31 | ((EntryChunk)processedchunk).ProcessAll(NSFController.GameVersion); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Unprocessed/UnprocessedEntryController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(UnprocessedEntry))] 6 | public sealed class UnprocessedEntryController : EntryController 7 | { 8 | public UnprocessedEntryController(UnprocessedEntry unprocessedentry, SubcontrollerGroup parentGroup) : base(unprocessedentry, parentGroup) 9 | { 10 | UnprocessedEntry = unprocessedentry; 11 | AddMenu(string.Format(CrashUI.Properties.Resources.UnprocessedEntryController_AcProcess, UnprocessedEntry.EName), Menu_Process_Entry); 12 | } 13 | 14 | public UnprocessedEntry UnprocessedEntry { get; } 15 | 16 | private void Menu_Process_Entry() 17 | { 18 | Entry processedentry; 19 | try 20 | { 21 | processedentry = UnprocessedEntry.Process(GameVersion); 22 | } 23 | catch (LoadAbortedException) 24 | { 25 | return; 26 | } 27 | int index = EntryChunkController.EntryChunk.Entries.IndexOf(UnprocessedEntry); 28 | EntryChunkController.EntryChunk.Entries[index] = processedentry; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CrashEdit/Controllers/Zone/OldCameraController.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [OrphanLegacyController(typeof(OldCamera))] 6 | public sealed class OldCameraController : LegacyController 7 | { 8 | public OldCameraController(OldCamera camera, SubcontrollerGroup parentGroup) : base(parentGroup, camera) 9 | { 10 | Camera = camera; 11 | AddMenu("Delete Camera", Menu_Delete); 12 | } 13 | 14 | public override bool EditorAvailable => true; 15 | 16 | public override Control CreateEditor() 17 | { 18 | return new OldCameraBox(this); 19 | } 20 | 21 | public ProtoZoneEntryController ProtoZoneEntryController => Modern.Parent.Legacy as ProtoZoneEntryController; 22 | public ProtoZoneEntry ProtoZoneEntry => ProtoZoneEntryController.ProtoZoneEntry; 23 | public OldZoneEntryController OldZoneEntryController => Modern.Parent.Legacy as OldZoneEntryController; 24 | public OldZoneEntry OldZoneEntry => OldZoneEntryController.OldZoneEntry; 25 | public OldCamera Camera { get; } 26 | 27 | private void Menu_Delete() 28 | { 29 | if (ProtoZoneEntryController != null) 30 | { 31 | ProtoZoneEntry.Cameras.Remove(Camera); 32 | ProtoZoneEntry.CameraCount = ProtoZoneEntry.Cameras.Count; 33 | } 34 | else 35 | { 36 | OldZoneEntry.Cameras.Remove(Camera); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CrashEdit/Controls/3D/ControlsKeyboardInfo.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | public sealed class ControlsKeyboardInfo 4 | { 5 | public Keys Key { get; } 6 | public string Instruction { get; } 7 | 8 | public ControlsKeyboardInfo(Keys key, string instruction) 9 | { 10 | Key = key; 11 | Instruction = instruction; 12 | } 13 | 14 | public string PrintKeys() 15 | { 16 | if ((Key & Keys.Modifiers) == 0) 17 | return Key.ToString(); 18 | 19 | string modifiers = (Key & Keys.Control) != 0 ? "Ctrl" : string.Empty; 20 | if ((Key & Keys.Shift) != 0) 21 | modifiers += string.IsNullOrEmpty(modifiers) ? "Shift" : " + Shift"; 22 | if ((Key & Keys.Alt) != 0) 23 | modifiers += string.IsNullOrEmpty(modifiers) ? "Alt" : " + Alt"; 24 | return (Key & Keys.KeyCode) == 0 ? modifiers : $"{modifiers} + {Key & Keys.KeyCode}"; 25 | } 26 | 27 | public string Print(params object[] args) => string.Format(PrintKeys() + ": " + Instruction + "\n", args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CrashEdit/Controls/GetAllControls.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | public static class ControlExt 4 | { 5 | public static IEnumerable GetAll(this Control control, Type type) 6 | { 7 | var controls = control.Controls.Cast(); 8 | return controls.SelectMany(ctrl => ctrl.GetAll(type)).Concat(controls).Where(c => c.GetType() == type); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CrashEdit/Controls/MysteryBox.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | public sealed class MysteryBox : UserControl 4 | { 5 | private byte[] data; 6 | private bool saving; 7 | 8 | private ToolStrip tsToolbar; 9 | private ToolStripButton tbbExport; 10 | private HexBox hbData; 11 | 12 | public MysteryBox(byte[] data) 13 | { 14 | this.data = data; 15 | saving = false; 16 | 17 | tbbExport = new ToolStripButton(); 18 | tbbExport.Text = "Export"; 19 | tbbExport.Click += new EventHandler(tbbExport_Click); 20 | 21 | tsToolbar = new ToolStrip(); 22 | tsToolbar.Dock = DockStyle.Top; 23 | tsToolbar.Items.Add(tbbExport); 24 | 25 | hbData = new HexBox(); 26 | hbData.Dock = DockStyle.Fill; 27 | hbData.Data = data; 28 | 29 | Controls.Add(hbData); 30 | Controls.Add(tsToolbar); 31 | } 32 | 33 | void tbbExport_Click(object sender, EventArgs e) 34 | { 35 | if (!saving) 36 | { 37 | saving = true; 38 | FileUtil.SaveFile(data, FileFilters.Any); 39 | saving = false; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CrashEdit/Controls/NSFBox.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public sealed class NSFBox : MainControl 6 | { 7 | public NSFBox(IUserInterface ui, LevelWorkspace ws) : base(ui, Controller.Make(ws, null)) 8 | { 9 | Workspace = ws; 10 | NSF = ws.NSF; 11 | NSFController = (NSFController)RootController.SubcontrollerGroups[0].Members[0].Legacy; 12 | 13 | Sync(); 14 | 15 | // this (should be) the NSF node. not very robust. 16 | ResourceTree.Nodes[1].Expand(); 17 | } 18 | 19 | public LevelWorkspace Workspace { get; } 20 | public NSF NSF { get; } 21 | public NSFController NSFController { get; } 22 | 23 | public override void Sync() 24 | { 25 | base.Sync(); 26 | } 27 | 28 | public override void Kill() 29 | { 30 | base.Kill(); 31 | NSFController.Kill(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CrashEdit/Controls/OldSLSTDeltaBox.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public sealed class OldSLSTDeltaBox : UserControl 6 | { 7 | private ListBox lstValues; 8 | 9 | public OldSLSTDeltaBox(OldSLSTDelta slstitem) 10 | { 11 | lstValues = new ListBox 12 | { 13 | Dock = DockStyle.Fill 14 | }; 15 | lstValues.Items.Add(string.Format("Type: {0}", 1)); 16 | lstValues.Items.Add(string.Format("Remove Nodes: {0}", slstitem.RemoveNodes.Count)); 17 | lstValues.Items.Add(string.Format("Add Nodes: {0}", slstitem.AddNodes.Count)); 18 | lstValues.Items.Add(string.Format("Swap Nodes: {0}", slstitem.SwapNodes.Count)); 19 | Controls.Add(lstValues); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Controls/OldSLSTSourceBox.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public sealed class OldSLSTSourceBox : UserControl 6 | { 7 | private ListBox lstValues; 8 | 9 | public OldSLSTSourceBox(OldSLSTSource slstitem) 10 | { 11 | lstValues = new ListBox 12 | { 13 | Dock = DockStyle.Fill 14 | }; 15 | lstValues.Items.Add(string.Format("Count: {0}", slstitem.Polygons.Count)); 16 | lstValues.Items.Add(string.Format("Type: {0}", 0)); 17 | foreach (OldSLSTPolygonID value in slstitem.Polygons) 18 | { 19 | lstValues.Items.Add(string.Format("Polygon {0} (World {1})", value.ID, value.World)); 20 | } 21 | Controls.Add(lstValues); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CrashEdit/Controls/PaletteEntryBox.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | using System.Drawing.Imaging; 3 | 4 | namespace CrashEdit.CE 5 | { 6 | public sealed class PaletteEntryBox : UserControl 7 | { 8 | public PaletteEntryBox(PaletteEntry entry) 9 | { 10 | Bitmap bitmap = new Bitmap(256, entry.Palettes.Length, PixelFormat.Format16bppArgb1555); 11 | Rectangle brect = new Rectangle(Point.Empty, bitmap.Size); 12 | BitmapData bdata = bitmap.LockBits(brect, ImageLockMode.WriteOnly, PixelFormat.Format16bppArgb1555); 13 | try 14 | { 15 | for (int y = 0; y < entry.Palettes.Length; ++y) 16 | { 17 | for (int x = 0; x < 256; ++x) 18 | { 19 | short color = BitConv.FromInt16(entry.Palettes[y], x * 2); 20 | PixelConv.Unpack1555(color, out byte alpha, out byte blue, out byte green, out byte red); 21 | color = PixelConv.Pack1555(1, red, green, blue); 22 | System.Runtime.InteropServices.Marshal.WriteInt16(bdata.Scan0, x * 2 + y * bdata.Stride, color); 23 | } 24 | } 25 | } 26 | finally 27 | { 28 | bitmap.UnlockBits(bdata); 29 | } 30 | PictureBox picture = new PictureBox(); 31 | picture.Dock = DockStyle.Fill; 32 | picture.Image = bitmap; 33 | Controls.Add(picture); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CrashEdit/Controls/SLSTDeltaBox.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public sealed class SLSTDeltaBox : UserControl 6 | { 7 | private ListBox lstValues; 8 | 9 | public SLSTDeltaBox(SLSTDelta slstitem) 10 | { 11 | lstValues = new ListBox 12 | { 13 | Dock = DockStyle.Fill 14 | }; 15 | lstValues.Items.Add(string.Format("Remove Nodes: {0}", slstitem.RemoveNodes.Count)); 16 | lstValues.Items.Add(string.Format("Add Nodes: {0}", slstitem.AddNodes.Count)); 17 | lstValues.Items.Add(string.Format("Swap Nodes: {0}", slstitem.SwapNodes.Count)); 18 | Controls.Add(lstValues); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CrashEdit/Controls/SLSTSourceBox.cs: -------------------------------------------------------------------------------- 1 | using CrashEdit.Crash; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public sealed class SLSTSourceBox : UserControl 6 | { 7 | private ListBox lstValues; 8 | 9 | public SLSTSourceBox(SLSTSource slstitem) 10 | { 11 | lstValues = new ListBox 12 | { 13 | Dock = DockStyle.Fill 14 | }; 15 | lstValues.Items.Add(string.Format("Count: {0}", slstitem.Polygons.Count)); 16 | foreach (SLSTPolygonID value in slstitem.Polygons) 17 | { 18 | lstValues.Items.Add(string.Format("Polygon {2}-{0} (World {1})", value.ID, value.World, value.State)); 19 | } 20 | Controls.Add(lstValues); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CrashEdit/FileFilters.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | public static class FileFilters 4 | { 5 | public const string Any = "All Files (*.*)|*.*"; 6 | public const string NSF = "Naughty Dog Software Files (*.nsf)|*.nsf;*.NSF"; 7 | public const string NSEntry = "Naughty Dog Software Entry (*.nsentry)|*.nsentry"; 8 | public const string Wave = "Wave Files (*.wav)|*.wav"; 9 | public const string OBJ = "Wavefront OBJ Files (*.obj)|*.obj"; 10 | public const string COLLADA = "COLLADA Files (*.dae)|*.dae"; 11 | public const string PLY = "Stanford PLY Files (*.ply)|*.ply"; 12 | public const string VH = "VAB Header Files (*.vh)|*.vh"; 13 | public const string VB = "VAB Body Files (*.vb)|*.vb"; 14 | public const string VAB = "VAB Files (*.vab)|*.vab"; 15 | public const string SEQ = "PS1 Sequence Files (*.seq)|*.seq"; 16 | public const string SEP = "PS1 Sequence Packages (*.sep)|*.sep"; 17 | public const string DLS = "Downloadable Sounds Files (*.dls)|*.dls"; 18 | public const string MIDI = "MIDI Files (*.mid)|*.mid"; 19 | public const string SVTX = "Vertex Animation Files (*.svtx)|*.svtx"; 20 | public const string PNG = "Portable Network Graphics (*.png)|*.png"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CrashEdit/Forms/InputWindow.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | public partial class InputWindow : Form 4 | { 5 | public InputWindow() 6 | { 7 | InitializeComponent(); 8 | 9 | cmdCancel.Text = Properties.Resources.InputWindow_cmdCancel; 10 | } 11 | 12 | public string Input => txtInput.Text; 13 | 14 | private void cmdOK_Click(object sender, EventArgs e) 15 | { 16 | DialogResult = DialogResult.OK; 17 | } 18 | 19 | private void cmdCancel_Click(object sender, EventArgs e) 20 | { 21 | DialogResult = DialogResult.Cancel; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CrashEdit/Forms/ProgressBarForm.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE.Forms 2 | { 3 | public partial class ProgressBarForm : Form 4 | { 5 | public ProgressBarForm() 6 | { 7 | InitializeComponent(); 8 | uxProgress.Invalidated += uxProgress_Invalidated; 9 | Shown += ProgressBarForm_Shown; 10 | } 11 | 12 | private void ProgressBarForm_Shown(object sender, System.EventArgs e) 13 | { 14 | IsShown = true; 15 | } 16 | 17 | private void uxProgress_Invalidated(object sender, InvalidateEventArgs e) 18 | { 19 | if (uxProgress.Value == 100) 20 | { 21 | Close(); 22 | } 23 | } 24 | 25 | public bool IsShown { get; set; } 26 | public ProgressBar ProgressBar => uxProgress; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CrashEdit/GUIException.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | [Serializable] 6 | public class GUIException : Exception 7 | { 8 | public GUIException(string message) : base(message) 9 | { 10 | } 11 | 12 | public GUIException(string message, Exception inner) : base(message, inner) 13 | { 14 | } 15 | 16 | protected GUIException(SerializationInfo info, StreamingContext context) : base(info, context) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CrashEdit/Render/ShaderFuncs.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public partial class ShaderInfo 6 | { 7 | public delegate void ShaderRenderFunc(Shader sh, RenderInfo ri, VAO vao); 8 | 9 | internal static void RenderDefault(Shader sh, RenderInfo ri, VAO vao) 10 | { 11 | } 12 | 13 | internal static void PreRenderDefault(Shader sh, RenderInfo ri, VAO vao) 14 | { 15 | sh.UniformMat4("projectionMatrix", ref ri.Projection.Perspective); 16 | sh.UniformMat4("viewMatrix", ref ri.Projection.View); 17 | Matrix4 pvm = ri.Projection.GetPVM(); 18 | sh.UniformMat4("PVM", ref pvm); 19 | sh.UniformVec3("viewTrans", ref ri.Projection.Trans); 20 | 21 | sh.UniformVec3("trans", ref vao.UserTrans); 22 | sh.UniformVec3("scale", ref vao.UserScale); 23 | sh.UniformInt("modeCull", vao.UserCullMode); 24 | sh.UniformInt("blendmask", vao.BlendMask); 25 | 26 | sh.UniformBool("disableDepth", vao.ZBufDisableWrite); 27 | sh.UniformBool("enableTex", ri.EnableTexture); 28 | } 29 | 30 | internal static void RenderOctree(Shader sh, RenderInfo ri, VAO vao) 31 | { 32 | sh.UniformFloat("uNodeShadeMax", vao.UserFloat); 33 | sh.UniformFloat("uNodeAlpha", vao.UserFloat2); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/crash1-generic.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec3 position; 4 | in vec3 normal; 5 | in vec4 color; 6 | in vec2 uv; 7 | in ivec2 tex; 8 | 9 | uniform mat4 PVM; 10 | 11 | uniform int blendmask; 12 | uniform int enableTex; 13 | 14 | out vec4 p_Color; 15 | out vec2 p_UV; 16 | out flat int p_Tex; 17 | out flat int p_TexPage; 18 | 19 | void main(void) 20 | { 21 | p_Color = vec4(color.rgb, 1.0); 22 | p_UV = uv; 23 | p_Tex = tex.x; 24 | p_TexPage = tex.y; 25 | 26 | if (p_TexPage >= 0 && enableTex != 0 && ((p_Tex >> 2) & 0x3) != blendmask && blendmask != 3) { 27 | // discard wrong blend modes, but always let textures pass on solid render 28 | gl_Position = vec4(0); 29 | } else { 30 | gl_Position = PVM * vec4( position, 1.0 ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/default4.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec4 p_Color; 4 | out vec4 f_Color; 5 | 6 | void main() 7 | { 8 | f_Color = p_Color; 9 | } 10 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/generic.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec3 position; 4 | in vec4 color; 5 | in vec2 uv; 6 | 7 | uniform mat4 PVM; 8 | 9 | uniform vec3 trans; 10 | uniform vec3 scale; 11 | uniform vec4 userColor1; 12 | 13 | out vec4 p_Color; 14 | out vec2 p_ST; 15 | 16 | void main() 17 | { 18 | gl_Position = PVM * vec4(position, 1.0); 19 | p_Color = color; 20 | p_ST = uv; 21 | } 22 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/line-static.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec4 position; 4 | in vec4 color; 5 | 6 | uniform mat4 PVM; 7 | 8 | out vec4 p_Color; 9 | 10 | void main() 11 | { 12 | gl_Position = PVM * position; 13 | p_Color = color; 14 | } 15 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/octree.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | layout(binding=3) uniform sampler2D tColors; 4 | layout(binding=4) uniform isampler3D tNodes; 5 | 6 | in vec3 pNode; 7 | 8 | uniform float uNodeShadeMax; 9 | uniform float uNodeAlpha; 10 | 11 | out vec4 fColor; 12 | 13 | void main() 14 | { 15 | int node = texelFetch(tNodes, ivec3(pNode), 0).r; 16 | if (node == 0) { 17 | discard; 18 | } else { 19 | int node_color = (node >> 1) & 0x7FFF; 20 | fColor = texelFetch(tColors, ivec2(node_color % 256, node_color >> 8), 0); 21 | 22 | // we got the color, now we add a bit of shading to help with depth perception 23 | // this 'packs' nodes such that they will accurately represent their layer in the octree 24 | vec3 packed_node = pNode / vec3(1 << ((node >> 16) & 0x1F), 1 << ((node >> 21) & 0x1F), 1 << ((node >> 26) & 0x1F)); 25 | vec3 packed_fracs = vec3(packed_node.x - trunc(packed_node.x), packed_node.y - trunc(packed_node.y), packed_node.z - trunc(packed_node.z)); 26 | // because the nodes are rendered on axis-aligned quads, only 2 axes can be non-integers, so we divide by 2 and not 3 27 | float shade = (packed_fracs.x + packed_fracs.y + packed_fracs.z) / 2 * uNodeShadeMax; 28 | fColor.rgb *= 1 - shade; 29 | fColor.a = uNodeAlpha; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/octree.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec3 position; 4 | in vec4 misc; 5 | 6 | uniform mat4 PVM; 7 | 8 | out vec3 pNode; 9 | 10 | void main() 11 | { 12 | gl_Position = PVM * vec4(position, 1.0); 13 | pNode = misc.xyz; 14 | } 15 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/screen.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | layout(binding=2) uniform sampler2D font; 4 | 5 | in vec4 p_Color; 6 | in vec2 p_ST; 7 | 8 | out vec4 f_Color; 9 | 10 | void main() 11 | { 12 | f_Color = p_Color; 13 | f_Color.a *= texture(font, p_ST).r; 14 | } 15 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/screen.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 position; 4 | in vec4 color; 5 | in vec2 uv; 6 | 7 | uniform vec3 scale; 8 | 9 | out vec4 p_Color; 10 | out vec2 p_ST; 11 | 12 | void main() 13 | { 14 | gl_Position = vec4((position * 2 / scale.xy) - 1.0, 0.0, 1.0); 15 | gl_Position.y = -gl_Position.y; 16 | p_Color = color; 17 | p_ST = uv; 18 | } 19 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/sprite-generic.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec3 position; 4 | in vec4 color; 5 | in vec2 uv; 6 | in vec4 misc; 7 | 8 | uniform mat4 PVM; 9 | uniform mat4 viewMatrix; 10 | 11 | out vec4 p_Color; 12 | out vec2 p_ST; 13 | 14 | void main() 15 | { 16 | gl_Position = PVM * vec4(position + misc.x * vec3(viewMatrix[0].x, viewMatrix[1].x, viewMatrix[2].x) 17 | + misc.y * vec3(viewMatrix[0].y, viewMatrix[1].y, viewMatrix[2].y) 18 | , 1.0); 19 | p_Color = color; 20 | p_ST = uv; 21 | } 22 | -------------------------------------------------------------------------------- /CrashEdit/Render/Shaders/sprite.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | layout(binding=1) uniform usampler2D sprites; 4 | 5 | in vec4 p_Color; 6 | in vec2 p_ST; 7 | 8 | out vec4 f_Color; 9 | 10 | void main() 11 | { 12 | f_Color = p_Color; 13 | 14 | ivec2 st = ivec2(p_ST.x, p_ST.y); 15 | // ivec2 sz = textureSize(sprites, 0); 16 | 17 | if (st.s <= -1) { 18 | // f_Color *= vec4(1, 0, 1, 1); 19 | } else { 20 | uvec4 texel = texelFetch(sprites, st, 0); 21 | if (texel.a == 0) discard; 22 | f_Color *= vec4(texel) / 255.0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CrashEdit/Resources/Icons/NSD.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Icons/NSD.ico -------------------------------------------------------------------------------- /CrashEdit/Resources/Icons/NSF.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Icons/NSF.ico -------------------------------------------------------------------------------- /CrashEdit/Resources/Icons/cbhacks-logo-new.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Icons/cbhacks-logo-new.ico -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/ActivatorBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/ActivatorBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Apple.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/AppleBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/AppleBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/ArrowBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/ArrowBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/BodyslamBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/BodyslamBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Box.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Checkpoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Checkpoint.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/DetonatorBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/DetonatorBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/DetonatorBoxTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/DetonatorBoxTop.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/IronArrowBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/IronArrowBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/IronBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/IronBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Life.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Life.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/LifeBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/LifeBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Mask.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/MaskBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/MaskBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Nitro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Nitro.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/NitroTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/NitroTop.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Point.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/QuestionMarkBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/QuestionMarkBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/TNT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/TNT.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/TNTTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/TNTTop.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Time1BoxTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Time1BoxTexture.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Time2BoxTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Time2BoxTexture.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/Time3BoxTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/Time3BoxTexture.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/TimeBoxTopTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/TimeBoxTopTexture.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/UnknownBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/UnknownBox.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/UnknownBoxTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/UnknownBoxTop.png -------------------------------------------------------------------------------- /CrashEdit/Resources/Textures/UnknownPickup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/Resources/Textures/UnknownPickup.png -------------------------------------------------------------------------------- /CrashEdit/Utils/ArrayRef.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | public static class ArrayUtil 4 | { 5 | public static ref T GetRefToElt(T[] array, int index) where T : struct 6 | { 7 | return ref array[index]; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /CrashEdit/Utils/GameScales.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | // scaling factors used across different types of art 4 | public static class GameScales 5 | { 6 | // Crash 1 7 | public const float AnimC1 = 128; 8 | public const float ModelC1 = 3200; 9 | public const float WorldC1 = 400; 10 | public const float CollisionC1 = 102400; 11 | public const float ZoneC1 = 400; 12 | public const float ZoneEntityC1 = 100; 13 | public const float ZoneCameraC1 = 400; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /CrashEdit/Utils/OpenTK Integration/EntityVisualList.cs: -------------------------------------------------------------------------------- 1 | namespace CrashEdit.CE 2 | { 3 | internal class EntityVisualList : Dictionary 4 | { 5 | public void AddVisual(int type, int subtype, EntityVisual visual) 6 | { 7 | int key = type * 100000 + subtype; 8 | if (ContainsKey(key)) 9 | this[key] = visual; 10 | else 11 | Add(key, visual); 12 | } 13 | 14 | public bool TryGetVisual(int type, int subtype, out EntityVisual visual) 15 | { 16 | return TryGetValue(type * 100000 + subtype, out visual); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CrashEdit/Utils/OpenTK Integration/TexturePageList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CrashEdit.CE 8 | { 9 | public sealed class TexturePageList : Dictionary 10 | { 11 | public void AddTexturePage(int eid) 12 | { 13 | if (!ContainsKey(eid)) 14 | this[eid] = (short)Count; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CrashEdit/Utils/ResourceLoad.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public static class ResourceLoad 6 | { 7 | public static string[] GetAllFileNames() => Assembly.GetExecutingAssembly().GetManifestResourceNames(); 8 | 9 | public static string LoadTextFile(string name) 10 | { 11 | var names = GetAllFileNames(); 12 | var exe = Assembly.GetExecutingAssembly(); 13 | var fullname = string.Format("{0}.{1}", "CrashEdit.CE", name.Replace("/", ".")); 14 | using var r = new StreamReader(exe.GetManifestResourceStream(fullname)); 15 | return r.ReadToEnd(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CrashEdit/Utils/StopwatchExt.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace CrashEdit.CE 4 | { 5 | public static class StopwatchExt 6 | { 7 | public static long ElapsedFrames(this Stopwatch watch) => watch.ElapsedTicks / TicksPerFrame; 8 | public static double ElapsedFramesFull(this Stopwatch watch) => watch.ElapsedTicks / (double)TicksPerFrame; 9 | public static long ElapsedFrameTime(this Stopwatch watch) => watch.ElapsedTicks % TicksPerFrame; 10 | public static double ElapsedSeconds(this Stopwatch watch) => watch.ElapsedTicks / (double)Stopwatch.Frequency; 11 | public static double ElapsedMillisecondsFull(this Stopwatch watch) => watch.ElapsedTicks / (Stopwatch.Frequency / 1000.0); 12 | public static long StopAndElapsed(this Stopwatch watch) 13 | { 14 | watch.Stop(); 15 | return watch.ElapsedTicks; 16 | } 17 | public static double StopAndElapsedMillisecondsFull(this Stopwatch watch) 18 | { 19 | watch.Stop(); 20 | return watch.ElapsedMillisecondsFull(); 21 | } 22 | 23 | public static long TicksPerFrame => Stopwatch.Frequency / 60; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CrashEdit/freetype6-win32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/freetype6-win32.dll -------------------------------------------------------------------------------- /CrashEdit/freetype6-win64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashEdit/freetype6-win64.dll -------------------------------------------------------------------------------- /CrashHacks/CrashHacks.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows 6 | enable 7 | true 8 | enable 9 | CrashHacks.MainClass 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | True 25 | True 26 | Resources.resx 27 | 28 | 29 | 30 | 31 | 32 | ResXFileCodeGenerator 33 | Resources.Designer.cs 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /CrashHacks/Main.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks 2 | { 3 | internal static class MainClass 4 | { 5 | [STAThread] 6 | private static void Main(string[] args) 7 | { 8 | Application.EnableVisualStyles(); 9 | using (MainForm mainform = new MainForm()) 10 | { 11 | if (args.Length >= 2) 12 | { 13 | mainform.TargetBIN = args[0]; 14 | mainform.SourceDir = args[1]; 15 | } 16 | Application.Run(mainform); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CrashHacks/Resources/input-gaming-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashHacks/Resources/input-gaming-3.png -------------------------------------------------------------------------------- /CrashHacks/Resources/media-optical-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/CrashHacks/Resources/media-optical-5.png -------------------------------------------------------------------------------- /CrashHacks/Script.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks 2 | { 3 | public abstract class Script 4 | { 5 | public abstract string Name 6 | { 7 | get; 8 | } 9 | 10 | public virtual string Description 11 | { 12 | get { return "No description available."; } 13 | } 14 | 15 | public virtual string Author 16 | { 17 | get { return "(unspecified)"; } 18 | } 19 | 20 | public virtual string Category 21 | { 22 | get { return "other"; } 23 | } 24 | 25 | public abstract SupportLevel CheckCompatibility(GameVersion gameversion); 26 | 27 | public abstract void Run(object value, GameVersion gameversion); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Animation/ReverseScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Animation 2 | { 3 | public sealed class ReverseScript : Script 4 | { 5 | public override string Name 6 | { 7 | get { return "Reverse all object animations"; } 8 | } 9 | 10 | public override string Description 11 | { 12 | get { return base.Description; } 13 | } 14 | 15 | public override string Author 16 | { 17 | get { return "chekwob"; } 18 | } 19 | 20 | public override string Category 21 | { 22 | get { return "animation"; } 23 | } 24 | 25 | public override SupportLevel CheckCompatibility(GameVersion gameversion) 26 | { 27 | switch (gameversion) 28 | { 29 | case GameVersion.Crash2: 30 | return SupportLevel.Supported; 31 | default: 32 | return SupportLevel.Untested; 33 | } 34 | } 35 | 36 | public override void Run(object value, GameVersion gameversion) 37 | { 38 | if (value is AnimationEntry entry) 39 | { 40 | List frames = new List(entry.Frames); 41 | frames.Reverse(); 42 | entry.Frames.Clear(); 43 | foreach (Frame frame in frames) 44 | { 45 | entry.Frames.Add(frame); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Scenery/Color/GrayscaleScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Scenery.Color 2 | { 3 | public sealed class GrayscaleScript : BaseScript 4 | { 5 | public override string Name 6 | { 7 | get { return "Make scenery colors grayscale"; } 8 | } 9 | 10 | public override string Description 11 | { 12 | get { return "Changes the colors used in scenery vertex coloring to grayscale by setting each color channel to the average of all of the color channels. Color introduced by textures is unaffected."; } 13 | } 14 | 15 | public override string Author 16 | { 17 | get { return "chekwob"; } 18 | } 19 | 20 | public override void Run(ref byte r, ref byte g, ref byte b) 21 | { 22 | byte avg = (byte)((r + g + b) / 3); 23 | r = avg; 24 | g = avg; 25 | b = avg; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Scenery/Color/NoBlueScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Scenery.Color 2 | { 3 | public sealed class NoBlueScript : BaseScript 4 | { 5 | public override string Name 6 | { 7 | get { return "Remove blue color from scenery"; } 8 | } 9 | 10 | public override string Description 11 | { 12 | get { return "Zeroes out the blue color channel used in scenery vertex coloring. Color introduced by textures is unaffected."; } 13 | } 14 | 15 | public override string Author 16 | { 17 | get { return "chekwob"; } 18 | } 19 | 20 | public override void Run(ref byte r, ref byte g, ref byte b) 21 | { 22 | b = 0; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Scenery/Color/NoGreenScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Scenery.Color 2 | { 3 | public sealed class NoGreenScript : BaseScript 4 | { 5 | public override string Name 6 | { 7 | get { return "Remove green color from scenery"; } 8 | } 9 | 10 | public override string Description 11 | { 12 | get { return "Zeroes out the green color channel used in scenery vertex coloring. Color introduced by textures is unaffected."; } 13 | } 14 | 15 | public override string Author 16 | { 17 | get { return "chekwob"; } 18 | } 19 | 20 | public override void Run(ref byte r, ref byte g, ref byte b) 21 | { 22 | g = 0; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Scenery/Color/NoRedScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Scenery.Color 2 | { 3 | public sealed class NoRedScript : BaseScript 4 | { 5 | public override string Name 6 | { 7 | get { return "Remove red color from scenery"; } 8 | } 9 | 10 | public override string Description 11 | { 12 | get { return "Zeroes out the red color channel used in scenery vertex coloring. Color introduced by textures is unaffected."; } 13 | } 14 | 15 | public override string Author 16 | { 17 | get { return "chekwob"; } 18 | } 19 | 20 | public override void Run(ref byte r, ref byte g, ref byte b) 21 | { 22 | r = 0; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Scenery/Color/RandomScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Scenery.Color 2 | { 3 | public sealed class RandomScript : BaseScript 4 | { 5 | private Random random; 6 | 7 | public RandomScript() 8 | { 9 | this.random = new Random(); 10 | } 11 | 12 | public override string Name 13 | { 14 | get { return "Rainbow scenery colors"; } 15 | } 16 | 17 | public override string Description 18 | { 19 | get { return "Fills the color channels for scenery vertex coloring with random values."; } 20 | } 21 | 22 | public override string Author 23 | { 24 | get { return "chekwob"; } 25 | } 26 | 27 | public override void Run(ref byte r, ref byte g, ref byte b) 28 | { 29 | r = (byte)random.Next(0, 256); 30 | g = (byte)random.Next(0, 256); 31 | b = (byte)random.Next(0, 256); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Scenery/FeastScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Scenery 2 | { 3 | public sealed class FeastScript : Script 4 | { 5 | public override string Name 6 | { 7 | get { return "FeastScript"; } 8 | } 9 | public override string Author 10 | { 11 | get { return "chekwob"; } 12 | } 13 | 14 | public override string Category 15 | { 16 | get { return "scenery"; } 17 | } 18 | 19 | public override SupportLevel CheckCompatibility(GameVersion gameversion) 20 | { 21 | return SupportLevel.Experimental; 22 | } 23 | 24 | public override void Run(object value, GameVersion gameversion) 25 | { 26 | if (value is SceneryEntry) 27 | { 28 | SceneryEntry entry = (SceneryEntry)value; 29 | if (entry.Colors.Count < 1) 30 | return; 31 | SceneryColor feast = new SceneryColor(0, 0, 0, 0); 32 | for (int i = 0; i < entry.Colors.Count; ++i) 33 | { 34 | SceneryColor newfeast = entry.Colors[i]; 35 | if (i != 0) 36 | entry.Colors[i] = new SceneryColor(feast.Red, feast.Green, feast.Blue, feast.Extra); 37 | feast = newfeast; 38 | } 39 | entry.Colors[0] = new SceneryColor(feast.Red, feast.Green, feast.Blue, feast.Extra); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Scenery/ScrumpScript.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Scenery 2 | { 3 | public sealed class ScrumpScript : Script 4 | { 5 | public override string Name 6 | { 7 | get { return "ScrumpScript"; } 8 | } 9 | public override string Author 10 | { 11 | get { return "chekwob"; } 12 | } 13 | 14 | public override string Category 15 | { 16 | get { return "scenery"; } 17 | } 18 | 19 | public override SupportLevel CheckCompatibility(GameVersion gameversion) 20 | { 21 | return SupportLevel.Experimental; 22 | } 23 | 24 | public override void Run(object value, GameVersion gameversion) 25 | { 26 | if (value is SceneryEntry) 27 | { 28 | UnprocessedEntry entry = ((SceneryEntry)value).Unprocess(); 29 | if (entry.Items[3].Length < 11) 30 | return; 31 | byte[] scrump = new byte[11]; 32 | for (int i = 0; i + 11 <= entry.Items[3].Length; i += 11) 33 | { 34 | byte[] newscrump = new byte[11]; 35 | Array.Copy(entry.Items[3], i, newscrump, 0, 11); 36 | if (i != 0) 37 | scrump.CopyTo(entry.Items[3], i); 38 | scrump = newscrump; 39 | } 40 | scrump.CopyTo(entry.Items[3], 0); 41 | value = entry.Process(gameversion); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /CrashHacks/Scripts/Zone/No298Script.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks.Scripts.Zone 2 | { 3 | public sealed class No298Script : Script 4 | { 5 | public override string Name 6 | { 7 | get { return "No298Script"; } 8 | } 9 | 10 | /*public override string Description 11 | { 12 | get { return "Disables the darkness effect used in levels such as Totally Fly and Totally Bear."; } 13 | }*/ 14 | 15 | public override string Author 16 | { 17 | get { return "chekwob"; } 18 | } 19 | 20 | public override string Category 21 | { 22 | get { return "zone"; } 23 | } 24 | 25 | public override SupportLevel CheckCompatibility(GameVersion gameversion) 26 | { 27 | return SupportLevel.Experimental; 28 | } 29 | 30 | public override void Run(object value, GameVersion gameversion) 31 | { 32 | if (value is ZoneEntry) 33 | { 34 | ZoneEntry entry = (ZoneEntry)value; 35 | foreach (Entity entity in entry.Entities) 36 | { 37 | entity.ExtraProperties.Remove(0x142); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CrashHacks/SupportLevel.cs: -------------------------------------------------------------------------------- 1 | namespace CrashHacks 2 | { 3 | public enum SupportLevel 4 | { 5 | Supported, 6 | Unsupported, 7 | Untested, 8 | Experimental 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CrashHacks/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CrashHacks/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Embeds/Images/Anchor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Anchor.gif -------------------------------------------------------------------------------- /Embeds/Images/Arrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Arrow.gif -------------------------------------------------------------------------------- /Embeds/Images/Erase.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Erase.gif -------------------------------------------------------------------------------- /Embeds/Images/File.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/File.gif -------------------------------------------------------------------------------- /Embeds/Images/Fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Fire.png -------------------------------------------------------------------------------- /Embeds/Images/Floppy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Floppy.gif -------------------------------------------------------------------------------- /Embeds/Images/Folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Folder.gif -------------------------------------------------------------------------------- /Embeds/Images/FolderOpen.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/FolderOpen.gif -------------------------------------------------------------------------------- /Embeds/Images/JournalBlue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/JournalBlue.gif -------------------------------------------------------------------------------- /Embeds/Images/JournalCode.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/JournalCode.gif -------------------------------------------------------------------------------- /Embeds/Images/JournalCyan.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/JournalCyan.gif -------------------------------------------------------------------------------- /Embeds/Images/JournalOrange.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/JournalOrange.gif -------------------------------------------------------------------------------- /Embeds/Images/JournalRed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/JournalRed.gif -------------------------------------------------------------------------------- /Embeds/Images/JournalWhite.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/JournalWhite.gif -------------------------------------------------------------------------------- /Embeds/Images/MagnifyingGlass.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/MagnifyingGlass.gif -------------------------------------------------------------------------------- /Embeds/Images/MusicNoteBlue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/MusicNoteBlue.gif -------------------------------------------------------------------------------- /Embeds/Images/MusicNoteRed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/MusicNoteRed.gif -------------------------------------------------------------------------------- /Embeds/Images/MusicNoteYellow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/MusicNoteYellow.gif -------------------------------------------------------------------------------- /Embeds/Images/Painting.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Painting.gif -------------------------------------------------------------------------------- /Embeds/Images/RecordFirst.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/RecordFirst.gif -------------------------------------------------------------------------------- /Embeds/Images/RecordLast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/RecordLast.gif -------------------------------------------------------------------------------- /Embeds/Images/RecordNext.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/RecordNext.gif -------------------------------------------------------------------------------- /Embeds/Images/RecordPrevious.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/RecordPrevious.gif -------------------------------------------------------------------------------- /Embeds/Images/Sitemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/Sitemap.png -------------------------------------------------------------------------------- /Embeds/Images/SpeakerBlue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/SpeakerBlue.gif -------------------------------------------------------------------------------- /Embeds/Images/SpeakerWhite.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/SpeakerWhite.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingBlue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingBlue.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingCode.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingCode.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingCrimson.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingCrimson.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingGray.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingGray.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingLime.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingLime.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingOrange.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingOrange.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingRed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingRed.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingViolet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingViolet.gif -------------------------------------------------------------------------------- /Embeds/Images/ThingYellow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbhacks/CrashEdit/f7a9bf997ff633677fd737a03038af33a63cb30d/Embeds/Images/ThingYellow.gif -------------------------------------------------------------------------------- /FTBitmapExtensions/FTBitmapExtensions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | True 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ISO2PSX/ISO2PSX.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Some images were obtained from "free icons web", with no license information 2 | provided other than "free": 3 | http://freeiconsweb.com/gif_icons.htm 4 | (Link is dead, can't find a replacement, sorry) 5 | 6 | Some images are part of various free icon packages from Aha-Soft, CC-BY 3.0 US. 7 | / 8 | 9 | Some images are from the FatCow free icon set, CC-BY 3.0 US. 10 | 11 | 12 | `Crash.Audio.SampleLine::ToPCM` and `Crash.Audio.ADPCMConv` are based 13 | directly off of some code from nextvolume's psxsdk (vag2wav.c), which claims 14 | it's "Based on VAG-Depack 0.1 by bITmASTER". 15 | 16 | This program is sometimes packaged with OpenTK, in which case the license for OpenTK will be included in a separate file. 17 | 18 | Aside from that, whatever. 19 | --------------------------------------------------------------------------------