private void RenderFullImage(Tiny64.Machine machine, GR.Image.MemoryImage img) { // render image bool vicActive = ((machine.Memory.VIC.ReadByte(0x11) & 0x10) != 0); if (vicActive) { int vicBank = (machine.Memory.CIA2.ReadByte(0) & 0x03) ^ 0x03; int screenPos = ((machine.Memory.VIC.ReadByte(0x18) & 0xf0) >> 4) * 1024 + vicBank * 16384; int localCharDataPos = (machine.Memory.VIC.ReadByte(0x18) & 0x0e) * 1024; int charDataPos = localCharDataPos + vicBank * 16384; byte bgColor = (byte)(machine.Memory.VIC.ReadByte(0x21) & 0x0f); GR.Memory.ByteBuffer charData = null; if (((vicBank == 0) || (vicBank == 2)) && (localCharDataPos == 0x1000)) { // use default upper case chars charData = new GR.Memory.ByteBuffer(); charData.Append(Machine.Memory.CharacterROM, 0, 2048); } else if (((vicBank == 0) || (vicBank == 2)) && (localCharDataPos == 0x2000)) { // use default lower case chars charData = new GR.Memory.ByteBuffer(); charData.Append(Machine.Memory.CharacterROM, 2048, 2048); } else { // use RAM charData = new GR.Memory.ByteBuffer(machine.Memory.RAM); charData = charData.SubBuffer(charDataPos, 2048); } for (int y = 0; y < 25; ++y) { for (int x = 0; x < 40; ++x) { byte charIndex = machine.Memory.RAM[screenPos + x + y * 40]; byte charColor = machine.Memory.ColorRAM[x + y * 40]; //CharacterDisplayer.DisplayHiResChar( charData.SubBuffer( charIndex * 8, 8 ), bgColor, charColor, img, x * 8, y * 8 ); } } /* * DataObject dataObj = new DataObject(); * * GR.Memory.ByteBuffer dibData = img.CreateHDIBAsBuffer(); * * System.IO.MemoryStream ms = dibData.MemoryStream(); * * // WTF - SetData requires streams, NOT global data (HGLOBAL) * dataObj.SetData( "DeviceIndependentBitmap", ms ); * Clipboard.SetDataObject( dataObj, true );*/ } }
private void btnOpenBinary_Click(object sender, EventArgs e) { OpenFileDialog openDialog = new OpenFileDialog(); openDialog.Title = "Choose binary file"; if (openDialog.ShowDialog() == DialogResult.OK) { m_OpenedFilename = openDialog.FileName; GR.Memory.ByteBuffer data = GR.IO.File.ReadAllBytes(openDialog.FileName); if (data != null) { ushort loadAddress = 0x801; if (System.IO.Path.GetExtension(openDialog.FileName).ToUpper() == ".PRG") { // treat first two bytes as load address loadAddress = data.UInt16At(0); data = data.SubBuffer(2); } m_Disassembler.SetData(data); m_DisassemblyProject.Data = data; editStartAddress.Text = "$" + loadAddress.ToString("X4"); int sysAddress = -1; if (m_Disassembler.HasBASICJumpAddress(loadAddress, out sysAddress)) { m_DisassemblyProject.JumpedAtAddresses.Add(sysAddress); ListViewItem item = new ListViewItem(); FillItemFromAddress(item, sysAddress); listJumpedAtAddresses.Items.Add(item); } else { // we have no jump address, assume first byte as address m_DisassemblyProject.JumpedAtAddresses.Add(loadAddress); ListViewItem item = new ListViewItem(); FillItemFromAddress(item, loadAddress); listJumpedAtAddresses.Items.Add(item); } SetHexData(data); UpdateDisassembly(); } } }
public override bool WriteFile(GR.Memory.ByteBuffer Filename, GR.Memory.ByteBuffer Content, Types.FileType Type) { _LastError = ""; int fileIndex = 0; foreach (FileRecord file in FileRecords) { if (file.EntryType == 0) { // free slot found file.EntryType = 1; file.C64FileType = Type; if (Type == Types.FileType.PRG) { file.StartAddress = Content.UInt16At(0); if (Content.Length < 2) { FileDatas[fileIndex] = new GR.Memory.ByteBuffer(); } else { FileDatas[fileIndex] = Content.SubBuffer(2); } } else { file.StartAddress = 0x0801; FileDatas[fileIndex] = new GR.Memory.ByteBuffer(Content); } file.EndAddress = (ushort)(file.StartAddress + Content.Length); file.FileOffset = 0; file.Filename = Filename; return(true); } ++fileIndex; } _LastError = "tape image is full"; return(false); }
private void btnReloadFile_Click(object sender, EventArgs e) { GR.Memory.ByteBuffer data = GR.IO.File.ReadAllBytes(m_OpenedFilename); if (data != null) { ushort loadAddress = 0x801; if (System.IO.Path.GetExtension(m_OpenedFilename).ToUpper() == ".PRG") { // treat first two bytes as load address loadAddress = data.UInt16At(0); data = data.SubBuffer(2); } m_Disassembler.SetData(data); m_DisassemblyProject.Data = data; SetHexData(data); UpdateDisassembly(); } }
public override bool WriteFile(GR.Memory.ByteBuffer Filename, GR.Memory.ByteBuffer Content, C64Studio.Types.FileType Type) { _LastError = ""; FileEntry file = new FileEntry(); file.Filename = new GR.Memory.ByteBuffer(Filename); file.Data = new GR.Memory.ByteBuffer(Content); if (Type == C64Studio.Types.FileType.PRG) { if (Content.Length >= 2) { file.StartAddress = Content.UInt16At(0); file.Data = Content.SubBuffer(2); } } file.EndAddress = (ushort)(file.StartAddress + file.Data.Length - 1); if (file.StartAddress + file.Data.Length >= 65536) { _LastError = "file size too large"; return(false); } TapFiles.Add(file); return(true); }
public bool ReadFromBuffer(GR.Memory.ByteBuffer DataIn) { if (DataIn == null) { return(false); } GR.IO.MemoryReader memIn = DataIn.MemoryReader(); uint version = memIn.ReadUInt32(); if (version == 1) { TotalNumberOfCharacters = 256; string name = memIn.ReadString(); string charsetFilename = memIn.ReadString(); for (int i = 0; i < TotalNumberOfCharacters; ++i) { Characters[i].Tile.CustomColor = memIn.ReadInt32(); } bool hasAnyMC = false; for (int i = 0; i < TotalNumberOfCharacters; ++i) { var mode = (TextCharMode)memIn.ReadUInt8(); if ((mode == TextCharMode.COMMODORE_MULTICOLOR) && (Characters[i].Tile.CustomColor < 8)) { mode = TextCharMode.COMMODORE_HIRES; } if (mode == TextCharMode.COMMODORE_MULTICOLOR) { hasAnyMC = true; } } Colors.BackgroundColor = memIn.ReadInt32(); Colors.MultiColor1 = memIn.ReadInt32(); Colors.MultiColor2 = memIn.ReadInt32(); for (int i = 0; i < TotalNumberOfCharacters; ++i) { int tileColor1 = memIn.ReadInt32(); int tileColor2 = memIn.ReadInt32(); int tileColor3 = memIn.ReadInt32(); int tileColor4 = memIn.ReadInt32(); int tileChar1 = memIn.ReadInt32(); int tileChar2 = memIn.ReadInt32(); int tileChar3 = memIn.ReadInt32(); int tileChar4 = memIn.ReadInt32(); } bool genericMulticolor = (memIn.ReadInt32() != 0); GR.Memory.ByteBuffer testbed = new GR.Memory.ByteBuffer(); memIn.ReadBlock(testbed, 64); GR.Memory.ByteBuffer charsetData = new GR.Memory.ByteBuffer(); memIn.ReadBlock(charsetData, (uint)(TotalNumberOfCharacters * 8)); for (int i = 0; i < TotalNumberOfCharacters; ++i) { Characters[i].Tile.Data = charsetData.SubBuffer(i * 8, 8); } UsedTiles = memIn.ReadUInt32(); ExportFilename = memIn.ReadString(); string exportPathBlockTable = memIn.ReadString(); string exportPathCharset = memIn.ReadString(); string exportPathEditorTiles = memIn.ReadString(); // categories Categories.Clear(); int categoryCount = memIn.ReadInt32(); for (int i = 0; i < categoryCount; ++i) { int catKey = memIn.ReadInt32(); string catName = memIn.ReadString(); Categories.Add(catName); } if (Categories.Count == 0) { // add default category Categories.Add("Uncategorized"); } for (int i = 0; i < TotalNumberOfCharacters; ++i) { Characters[i].Category = memIn.ReadInt32(); if ((Characters[i].Category < 0) || (Characters[i].Category >= Categories.Count)) { Characters[i].Category = 0; } } ExportNumCharacters = memIn.ReadInt32(); if (ExportNumCharacters < TotalNumberOfCharacters) { ExportNumCharacters = TotalNumberOfCharacters; } ShowGrid = (memIn.ReadInt32() != 0); ExportStartCharacter = memIn.ReadInt32(); Colors.BGColor4 = memIn.ReadInt32(); // playground int w = memIn.ReadInt32(); int h = memIn.ReadInt32(); if (w * h < 256) { w = 16; h = 16; } PlaygroundChars = new List <uint>(w * h); for (int i = 0; i < w * h; ++i) { ushort charInfo = memIn.ReadUInt16(); PlaygroundChars.Add((uint)((charInfo & 0xff) | ((charInfo & 0xff00) << 8))); } Mode = (TextCharMode)memIn.ReadInt32(); if (hasAnyMC) { Mode = TextCharMode.COMMODORE_MULTICOLOR; } } else if (version == 2) { Characters.Clear(); Categories.Clear(); Colors.Palettes.Clear(); TotalNumberOfCharacters = 256; Mode = TextCharMode.COMMODORE_HIRES; var chunk = new GR.IO.FileChunk(); while (chunk.ReadFromStream(memIn)) { if (chunk.Type == FileChunkConstants.CHARSET_PROJECT) { var chunkIn = chunk.MemoryReader(); var subChunk = new GR.IO.FileChunk(); while (subChunk.ReadFromStream(chunkIn)) { var subMemIn = subChunk.MemoryReader(); switch (subChunk.Type) { case FileChunkConstants.CHARSET_INFO: Mode = (TextCharMode)subMemIn.ReadInt32(); TotalNumberOfCharacters = subMemIn.ReadInt32(); ShowGrid = ((subMemIn.ReadInt32() & 1) == 1); break; case FileChunkConstants.CHARSET_COLOR_SETTINGS: Colors.BackgroundColor = subMemIn.ReadInt32(); Colors.MultiColor1 = subMemIn.ReadInt32(); Colors.MultiColor2 = subMemIn.ReadInt32(); Colors.BGColor4 = subMemIn.ReadInt32(); Colors.ActivePalette = subMemIn.ReadInt32(); break; case FileChunkConstants.PALETTE: Colors.Palettes.Add(Palette.Read(subMemIn)); break; case FileChunkConstants.CHARSET_EXPORT: ExportStartCharacter = subMemIn.ReadInt32(); ExportNumCharacters = subMemIn.ReadInt32(); ExportFilename = subMemIn.ReadString(); break; case FileChunkConstants.CHARSET_CHAR: { var charData = new CharData(); subMemIn.ReadInt32(); // was TextCharMode charData.Tile.CustomColor = subMemIn.ReadInt32(); charData.Tile.Mode = Lookup.GraphicTileModeFromTextCharMode(Mode, charData.Tile.CustomColor); charData.Category = subMemIn.ReadInt32(); int dataLength = subMemIn.ReadInt32(); charData.Tile.Data = new GR.Memory.ByteBuffer(); subMemIn.ReadBlock(charData.Tile.Data, (uint)dataLength); Characters.Add(charData); } break; case FileChunkConstants.CHARSET_CATEGORY: Categories.Add(subMemIn.ReadString()); break; case FileChunkConstants.CHARSET_PLAYGROUND: PlaygroundWidth = subMemIn.ReadInt32(); PlaygroundHeight = subMemIn.ReadInt32(); PlaygroundChars = new List <uint>(PlaygroundWidth * PlaygroundHeight); for (int i = 0; i < PlaygroundWidth * PlaygroundHeight; ++i) { // 16 bit index, 16 bit color PlaygroundChars.Add(subMemIn.ReadUInt32()); } break; } } } } if (Colors.Palettes.Count == 0) { Colors.Palettes.Add(PaletteManager.PaletteFromNumColors(Lookup.NumberOfColorsInCharacter(Mode))); } } else { return(false); } return(true); }
public bool ReadFromBuffer(GR.Memory.ByteBuffer DataIn) { GR.IO.MemoryReader memIn = DataIn.MemoryReader(); uint version = memIn.ReadUInt32(); string name = memIn.ReadString(); string charsetFilename = memIn.ReadString(); for (int i = 0; i < 256; ++i) { Characters[i].Color = memIn.ReadInt32(); } for (int i = 0; i < 256; ++i) { Characters[i].Multicolor = (memIn.ReadUInt8() != 0); } BackgroundColor = memIn.ReadInt32(); MultiColor1 = memIn.ReadInt32(); MultiColor2 = memIn.ReadInt32(); for (int i = 0; i < 256; ++i) { int tileColor1 = memIn.ReadInt32(); int tileColor2 = memIn.ReadInt32(); int tileColor3 = memIn.ReadInt32(); int tileColor4 = memIn.ReadInt32(); int tileChar1 = memIn.ReadInt32(); int tileChar2 = memIn.ReadInt32(); int tileChar3 = memIn.ReadInt32(); int tileChar4 = memIn.ReadInt32(); } bool genericMulticolor = (memIn.ReadInt32() != 0); GR.Memory.ByteBuffer testbed = new GR.Memory.ByteBuffer(); memIn.ReadBlock(testbed, 64); GR.Memory.ByteBuffer charsetData = new GR.Memory.ByteBuffer(); memIn.ReadBlock(charsetData, 2048); for (int i = 0; i < 256; ++i) { Characters[i].Data = charsetData.SubBuffer(i * 8, 8); } UsedTiles = memIn.ReadUInt32(); ExportFilename = memIn.ReadString(); string exportPathBlockTable = memIn.ReadString(); string exportPathCharset = memIn.ReadString(); string exportPathEditorTiles = memIn.ReadString(); // categories Categories.Clear(); int categoryCount = memIn.ReadInt32(); for (int i = 0; i < categoryCount; ++i) { int catKey = memIn.ReadInt32(); string catName = memIn.ReadString(); Categories[catKey] = catName; } if (Categories.Count == 0) { // add default category Categories[0] = "Uncategorized"; } for (int i = 0; i < 256; ++i) { Characters[i].Category = memIn.ReadInt32(); } return(true); }
public void UpdateValue( RequestData WatchData, GR.Memory.ByteBuffer Data ) { int delta = WatchData.AdjustedStartAddress - WatchData.Parameter1; int expectedSize = (int)Data.Length; if ( ( WatchData.MemDumpOffsetX ) || ( WatchData.MemDumpOffsetY ) ) { delta -= WatchData.AppliedOffset; } if ( WatchData.Parameter2 != -1 ) { expectedSize = WatchData.Parameter2 - WatchData.Parameter1 + 1; } if ( delta > 0 ) { // offset had to be adjusted due to VICE weird binary offset/end offset format if ( delta < Data.Length ) { UpdateValue( WatchData.Info, WatchData.MemDumpOffsetX, WatchData.MemDumpOffsetY, Data.SubBuffer( delta, expectedSize ) ); } } else if ( expectedSize < Data.Length ) { UpdateValue( WatchData.Info, WatchData.MemDumpOffsetX, WatchData.MemDumpOffsetY, Data.SubBuffer( 0, expectedSize ) ); } else { UpdateValue( WatchData.Info, WatchData.MemDumpOffsetX, WatchData.MemDumpOffsetY, Data ); } }
public override bool Load(string Filename) { _LastError = ""; Clear(); GR.Memory.ByteBuffer data = GR.IO.File.ReadAllBytes(Filename); if (data == null) { _LastError = "could not open/read file"; return(false); } if (data.Length < 64) { _LastError = "file size is too small"; return(false); } // Tape Header // 0 32 DOS tape description + EOF (for type) // 32 2 tape version ($0200) // 34 2 number of directory entries // 36 2 number of used entries (can be 0 in my loader) // 38 2 free // 40 24 user description as displayed in tape menu for (int i = 0; i < 32; ++i) { if (data.ByteAt(i) == (char)0x1a) { break; } TapeInfo.Description += (char)data.ByteAt(i); } ushort version = data.UInt16At(32); /* * if ( version != 0x0200 ) * { * return false; * }*/ TapeInfo.NumberEntries = data.UInt16At(34); TapeInfo.NumberUsedEntries = data.UInt16At(36); for (int i = 0; i < 24; ++i) { if (data.ByteAt(40 + i) == (char)0x20) { break; } TapeInfo.UserDescription += (char)data.ByteAt(i); } int entryPos = 64; for (int i = 0; i < TapeInfo.NumberEntries; ++i) { // File Header // Offset Size Description // 0 1 entry type (see below) // 1 1 C64 file type // 2 2 start address // 4 2 end address // 6 2 free // 8 4 offset of file contents start within T64 file // 12 4 free // 16 16 C64 file name // Code Explanation // 0 free entry // 1 normal tape file // 2 tape file with header: header is saved just before file data // 3 memory snapshot v0.9, uncompressed // 4 tape block // 5 digitized stream // 6 ... 255 reserved FileRecord file = new FileRecord(); file.EntryType = data.ByteAt(entryPos + 0); if ((file.EntryType != 1) && (file.EntryType != 0)) { // unsupported type! _LastError = "unsupported entry type"; return(false); } if (file.EntryType == 0) { FileRecords.Add(file); FileDatas.Add(new GR.Memory.ByteBuffer()); entryPos += 32; continue; } file.C64FileType = (Types.FileType)data.ByteAt(entryPos + 1); file.StartAddress = data.UInt16At(entryPos + 2); file.EndAddress = data.UInt16At(entryPos + 4); file.FileOffset = data.UInt32At(entryPos + 8); for (int j = 0; j < 16; ++j) { file.Filename.AppendU8(data.ByteAt(entryPos + 16 + j)); } FileRecords.Add(file); FileDatas.Add(data.SubBuffer((int)file.FileOffset, (int)(file.EndAddress - file.StartAddress))); entryPos += 32; } return(true); }
private bool LoadVersion5(GR.Memory.ByteBuffer Data) { BackgroundColor = Data.ByteAt(4); MultiColor1 = Data.ByteAt(5); MultiColor2 = Data.ByteAt(6); CustomColor = Data.ByteAt(7); TileColorMode = (ColorMode)Data.ByteAt(8); byte flags = Data.ByteAt(9); bool noTiles = ((flags & 0x01) == 0); MultiColor = ((flags & 0x04) != 0); bool isExpanded = ((flags & 0x02) != 0); NumChars = Data.UInt16At(10) + 1; NumTiles = Data.UInt16At(12) + 1; TileWidth = Data.ByteAt(14); TileHeight = Data.ByteAt(15); MapWidth = Data.UInt16At(16); MapHeight = Data.UInt16At(18); if (noTiles) { // fake tiles TileWidth = 1; TileHeight = 1; NumTiles = 256; } int headerSize = 20; int offsetToCharData = headerSize; int offsetToCharAttribs = offsetToCharData + NumChars * 8; int offsetToTileData = offsetToCharAttribs + NumChars; int offsetToTileColors = offsetToTileData + NumTiles * TileWidth * TileHeight * 2; if ((isExpanded) || (noTiles)) { offsetToTileColors = offsetToTileData; } int offsetToMapData = offsetToTileColors + NumTiles; if ((TileColorMode != ColorMode.PER_TILE) || (noTiles)) { offsetToMapData = offsetToTileColors; } // char_data/char_attribs for (int charIndex = 0; charIndex < NumChars; ++charIndex) { SingleChar newChar = new SingleChar(); newChar.Data = Data.SubBuffer(offsetToCharData + charIndex * 8, 8); if (TileColorMode == ColorMode.PER_TILE_CELL) { newChar.Color = Data.ByteAt(offsetToCharAttribs + charIndex) & 0x0f; } else { newChar.Color = CustomColor; } Characters.Add(newChar); } // tile_data if (noTiles) { for (int i = 0; i < NumTiles; ++i) { Tile tile = new Tile(); tile.CharData.Resize((uint)(TileWidth * TileHeight * 2)); tile.CharData.SetU16At(0, (ushort)i); tile.ColorData.Resize((uint)(TileWidth * TileHeight)); tile.ColorData.SetU8At(0, (byte)CustomColor); Tiles.Add(tile); } if (NumChars < 256) { // add all chars for safety reasons for (int i = NumChars; i < 256; ++i) { SingleChar newChar = new SingleChar(); newChar.Data = new GR.Memory.ByteBuffer(8); if (TileColorMode == ColorMode.PER_TILE_CELL) { newChar.Color = Data.ByteAt(offsetToCharAttribs + i) & 0x0f; } else { newChar.Color = CustomColor; } Characters.Add(newChar); } } } else { for (int i = 0; i < NumTiles; ++i) { Tile tile = new Tile(); tile.CharData.Resize((uint)(TileWidth * TileHeight * 2)); tile.ColorData.Resize((uint)(TileWidth * TileHeight)); Tiles.Add(tile); } if (isExpanded) { byte curCharIndex = 0; for (int i = 0; i < NumTiles; ++i) { for (int j = 0; j < TileWidth * TileHeight; ++j) { Tiles[i].CharData.SetU16At(j * 2, curCharIndex); ++curCharIndex; } } } else { // tile_data. Size = NUM_TILES * TILE_WIDTH * TILE_HEIGHT bytes * 2 bytes. (only exists if CHAR_DATA is not "Expanded") for (int i = 0; i < NumTiles; ++i) { for (int j = 0; j < TileWidth * TileHeight; ++j) { Tiles[i].CharData.SetU16At(j * 2, Data.UInt16At(offsetToTileData + i * TileWidth * TileHeight * 2 + j * 2)); } } } } // TILE_COLOURS. Size = NUM_TILES bytes (1 byte per tile = "RAM colour". only exists if COLOR_MODE = 1 (Per Tile) if (TileColorMode == ColorMode.PER_TILE) { for (int i = 0; i < NumTiles; ++i) { for (int y = 0; y < TileHeight; ++y) { for (int x = 0; x < TileWidth; ++x) { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetToTileColors + i) & 0x0f)); } } } } else if (TileColorMode == ColorMode.PER_TILE_CELL) { // with V5 this actually means per character for (int i = 0; i < NumTiles; ++i) { for (int y = 0; y < TileHeight; ++y) { for (int x = 0; x < TileWidth; ++x) { byte charColor = (byte)Characters[Tiles[i].CharData.ByteAt(2 * (x + y * TileWidth))].Color; Tiles[i].ColorData.SetU8At(x + y * TileWidth, charColor); } } } } else if (TileColorMode == ColorMode.GLOBAL) { for (int i = 0; i < NumTiles; ++i) { for (int y = 0; y < TileHeight; ++y) { for (int x = 0; x < TileWidth; ++x) { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)CustomColor); } } } } /* * else if ( TileColorMode == ColorMode.PER_TILE_CELL ) * { * for ( int i = 0; i < NumTiles; ++i ) * { * for ( int y = 0; y < TileHeight; ++y ) * { * for ( int x = 0; x < TileWidth; ++x ) * { * Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight ) & 0x0f ) ); * } * } * } * }*/ // MAP_DATA. Size = MAP_WID x MAP_HEI bytes. // tile indices are now 16 bit! for now force 8bit //MapData = Data.SubBuffer( offsetMapData, MapWidth * MapHeight * 2 ); MapData = new GR.Memory.ByteBuffer((uint)(MapWidth * MapHeight)); for (int i = 0; i < MapHeight; ++i) { for (int j = 0; j < MapWidth; ++j) { MapData.SetU8At(i * MapWidth + j, Data.ByteAt(offsetToMapData + 2 * (i * MapWidth + j))); } } return(true); }
private bool LoadVersion4(GR.Memory.ByteBuffer Data) { BackgroundColor = Data.ByteAt(4); MultiColor1 = Data.ByteAt(5); MultiColor2 = Data.ByteAt(6); CustomColor = Data.ByteAt(7); TileColorMode = (ColorMode)Data.ByteAt(8); MultiColor = (Data.ByteAt(9) != 0); NumChars = Data.UInt16At(10) + 1; NumTiles = Data.ByteAt(12) + 1; TileWidth = Data.ByteAt(13); TileHeight = Data.ByteAt(14); MapWidth = Data.UInt16At(15); MapHeight = Data.UInt16At(17); bool isExpanded = (Data.ByteAt(19) != 0); int offsetToCharAttribs = 24 + NumChars * 8; for (int charIndex = 0; charIndex < NumChars; ++charIndex) { SingleChar newChar = new SingleChar(); newChar.Data = Data.SubBuffer(24 + charIndex * 8, 8); newChar.Color = Data.ByteAt(offsetToCharAttribs + charIndex) & 0x0f; Characters.Add(newChar); } for (int i = 0; i < NumTiles; ++i) { Tile tile = new Tile(); tile.CharData.Resize((uint)(TileWidth * TileHeight * 2)); tile.ColorData.Resize((uint)(TileWidth * TileHeight)); Tiles.Add(tile); } if (isExpanded) { byte curCharIndex = 0; for (int i = 0; i < NumTiles; ++i) { for (int j = 0; j < TileWidth * TileHeight; ++j) { Tiles[i].CharData.SetU16At(j * 2, curCharIndex); ++curCharIndex; } } } else { // CELL_DATA. Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes * 2 bytes. (only exists if CHAR_DATA is not "Expanded") int offsetCellData = 24 + NumChars * 8 + NumChars; for (int i = 0; i < NumTiles; ++i) { for (int j = 0; j < TileWidth * TileHeight; ++j) { Tiles[i].CharData.SetU16At(j * 2, Data.UInt16At(offsetCellData + i * TileWidth * TileHeight * 2 + j * 2)); } } } // CELL_ATTRIBS. Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes (exists for ALL modes) int offsetCellAttribs = 24 + NumChars * 8 + NumChars; if (!isExpanded) { offsetCellAttribs += NumTiles * TileWidth * TileHeight * 2; } for (int i = 0; i < NumTiles; ++i) { for (int y = 0; y < TileHeight; ++y) { for (int x = 0; x < TileWidth; ++x) { if (TileColorMode == ColorMode.PER_TILE_CELL) { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight) & 0x0f)); } else { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)CustomColor); } } } } // TILE_ATTRIBS. Size = NUM_TILES bytes (1 byte per tile = "RAM colour". only exists if COLOR_MODE = 1 (Per Tile) int offsetTileAttribs = offsetCellAttribs + NumTiles * TileWidth * TileHeight; if (TileColorMode == ColorMode.PER_TILE) { for (int i = 0; i < NumTiles; ++i) { for (int y = 0; y < TileHeight; ++y) { for (int x = 0; x < TileWidth; ++x) { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetTileAttribs + i) & 0x0f)); } } } } /* * if ( TileColorMode == ColorMode.PER_TILE_CELL ) * { * for ( int i = 0; i < NumTiles; ++i ) * { * for ( int y = 0; y < TileHeight; ++y ) * { * for ( int x = 0; x < TileWidth; ++x ) * { * Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight ) & 0x0f ) ); * } * } * } * }*/ // MAP_DATA. Size = MAP_WID x MAP_HEI bytes. int offsetMapData = offsetTileAttribs; if (TileColorMode == ColorMode.PER_TILE) { offsetMapData += NumTiles; } MapData = Data.SubBuffer(offsetMapData, MapWidth * MapHeight); return(true); }
public bool ReadFromBuffer(GR.Memory.ByteBuffer DataIn) { if (DataIn == null) { return(false); } GR.IO.MemoryReader memIn = DataIn.MemoryReader(); uint version = memIn.ReadUInt32(); string name = memIn.ReadString(); string charsetFilename = memIn.ReadString(); for (int i = 0; i < 256; ++i) { Characters[i].Color = memIn.ReadInt32(); } for (int i = 0; i < 256; ++i) { Characters[i].Mode = (Types.CharsetMode)memIn.ReadUInt8(); } BackgroundColor = memIn.ReadInt32(); MultiColor1 = memIn.ReadInt32(); MultiColor2 = memIn.ReadInt32(); for (int i = 0; i < 256; ++i) { int tileColor1 = memIn.ReadInt32(); int tileColor2 = memIn.ReadInt32(); int tileColor3 = memIn.ReadInt32(); int tileColor4 = memIn.ReadInt32(); int tileChar1 = memIn.ReadInt32(); int tileChar2 = memIn.ReadInt32(); int tileChar3 = memIn.ReadInt32(); int tileChar4 = memIn.ReadInt32(); } bool genericMulticolor = (memIn.ReadInt32() != 0); GR.Memory.ByteBuffer testbed = new GR.Memory.ByteBuffer(); memIn.ReadBlock(testbed, 64); GR.Memory.ByteBuffer charsetData = new GR.Memory.ByteBuffer(); memIn.ReadBlock(charsetData, 2048); for (int i = 0; i < 256; ++i) { Characters[i].Data = charsetData.SubBuffer(i * 8, 8); } UsedTiles = memIn.ReadUInt32(); ExportFilename = memIn.ReadString(); string exportPathBlockTable = memIn.ReadString(); string exportPathCharset = memIn.ReadString(); string exportPathEditorTiles = memIn.ReadString(); // categories Categories.Clear(); int categoryCount = memIn.ReadInt32(); for (int i = 0; i < categoryCount; ++i) { int catKey = memIn.ReadInt32(); string catName = memIn.ReadString(); Categories.Add(catName); } if (Categories.Count == 0) { // add default category Categories.Add("Uncategorized"); } for (int i = 0; i < 256; ++i) { Characters[i].Category = memIn.ReadInt32(); if ((Characters[i].Category < 0) || (Characters[i].Category >= Categories.Count)) { Characters[i].Category = 0; } } NumCharacters = memIn.ReadInt32(); if (NumCharacters == 0) { NumCharacters = 256; } ShowGrid = (memIn.ReadInt32() != 0); StartCharacter = memIn.ReadInt32(); BGColor4 = memIn.ReadInt32(); // playground int w = memIn.ReadInt32(); int h = memIn.ReadInt32(); if (w * h < 256) { w = 16; h = 16; } PlaygroundChars = new List <ushort>(w * h); for (int i = 0; i < w * h; ++i) { PlaygroundChars.Add(memIn.ReadUInt16()); } return(true); }
public void ConvertScreens(string BasePath, List <string> ProjectFiles) { var projects = new List <RetroDevStudio.Formats.GraphicScreenProject>(); foreach (var file in ProjectFiles) { var project = new RetroDevStudio.Formats.GraphicScreenProject(); project.ReadFromBuffer(GR.IO.File.ReadAllBytes(file)); projects.Add(project); } int numChars = 0; foreach (var project in projects) { numChars += ((project.Image.Width + 7) / 8) * ((project.Image.Height + 7) / 8); } for (int i = 0; i < numChars; ++i) { m_Chars.Add(new RetroDevStudio.Formats.CharData()); } int curCharOffset = 0; int projectIndex = 0; foreach (var project in projects) { if (CheckForMCCharsetErrors(project, curCharOffset)) { Debug.Log("Found error in " + ProjectFiles[projectIndex]); return; } curCharOffset += ((project.Image.Width + 7) / 8) * ((project.Image.Height + 7) / 8); ++projectIndex; } if (CheckForDuplicates()) { // charset GR.Memory.ByteBuffer charSet = new GR.Memory.ByteBuffer(); foreach (var charInfo in m_Chars) { if (charInfo.Replacement == null) { charSet.Append(charInfo.Tile.Data); } } GR.IO.File.WriteAllBytes(System.IO.Path.Combine(BasePath, "combined.chr"), charSet); // screens int charIndexOffset = 0; projectIndex = 0; foreach (var project in projects) { // create screens from graphic var screen = new RetroDevStudio.Formats.CharsetScreenProject(); int blockWidth = ((project.Image.Width + 7) / 8); int blockHeight = ((project.Image.Height + 7) / 8); screen.SetScreenSize(blockWidth, blockHeight); for (int y = 0; y < blockHeight; ++y) { for (int x = 0; x < blockWidth; ++x) { var charData = m_Chars[charIndexOffset + x + y * blockWidth]; var origCharData = charData; while (charData.Replacement != null) { charData = charData.Replacement; } screen.Chars[x + y * blockWidth] = (ushort)((origCharData.Tile.CustomColor << 8) + charData.Index); screen.Mode = project.MultiColor ? RetroDevStudio.TextMode.COMMODORE_40_X_25_MULTICOLOR : RetroDevStudio.TextMode.COMMODORE_40_X_25_HIRES; screen.CharSet.Colors.MultiColor1 = project.Colors.MultiColor1; screen.CharSet.Colors.MultiColor2 = project.Colors.MultiColor2; screen.CharSet.Colors.BackgroundColor = project.Colors.BackgroundColor; } } screen.CharSet = new RetroDevStudio.Formats.CharsetProject(); screen.CharSet.Colors.BackgroundColor = project.Colors.BackgroundColor; screen.CharSet.Colors.MultiColor1 = project.Colors.MultiColor1; screen.CharSet.Colors.MultiColor2 = project.Colors.MultiColor2; for (uint c = 0; c < charSet.Length / 8; ++c) { screen.CharSet.Characters[(int)c].Tile.Data = charSet.SubBuffer((int)c * 8, 8); screen.CharSet.Characters[(int)c].Tile.CustomColor = 9; } string origFile = System.IO.Path.GetFileNameWithoutExtension(ProjectFiles[projectIndex]); GR.IO.File.WriteAllBytes(System.IO.Path.Combine(BasePath, origFile + ".charscreen"), screen.SaveToBuffer()); ++projectIndex; charIndexOffset += blockWidth * blockHeight; } } }
public bool LoadFromFile(GR.Memory.ByteBuffer Data) { Characters.Clear(); MapData.Clear(); if ((Data == null) || (Data.Length < 24) || (Data.ByteAt(0) != 'C') || (Data.ByteAt(1) != 'T') || (Data.ByteAt(2) != 'M')) { // not a valid CTM file return(false); } int version = Data.ByteAt(3); if (version != 4) { System.Windows.Forms.MessageBox.Show("Currently only version 4 of Charpad project files is supported. Sorry!", "Unsupported version " + version); return(false); } BackgroundColor = Data.ByteAt(4); MultiColor1 = Data.ByteAt(5); MultiColor2 = Data.ByteAt(6); CustomColor = Data.ByteAt(7); TileColorMode = (ColorMode)Data.ByteAt(8); MultiColor = (Data.ByteAt(9) != 0); NumChars = Data.UInt16At(10) + 1; NumTiles = Data.ByteAt(12) + 1; TileWidth = Data.ByteAt(13); TileHeight = Data.ByteAt(14); MapWidth = Data.UInt16At(15); MapHeight = Data.UInt16At(17); bool isExpanded = (Data.ByteAt(19) != 0); int offsetToCharAttribs = 24 + NumChars * 8; for (int charIndex = 0; charIndex < NumChars; ++charIndex) { SingleChar newChar = new SingleChar(); newChar.Data = Data.SubBuffer(24 + charIndex * 8, 8); newChar.Color = Data.ByteAt(offsetToCharAttribs + charIndex) & 0x0f; Characters.Add(newChar); } for (int i = 0; i < NumTiles; ++i) { Tile tile = new Tile(); tile.CharData.Resize((uint)(TileWidth * TileHeight * 2)); tile.ColorData.Resize((uint)(TileWidth * TileHeight)); Tiles.Add(tile); } if (isExpanded) { byte curCharIndex = 0; for (int i = 0; i < NumTiles; ++i) { for (int j = 0; j < TileWidth * TileHeight; ++j) { Tiles[i].CharData.SetU16At(j * 2, curCharIndex); ++curCharIndex; } } } else { // CELL_DATA. Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes * 2 bytes. (only exists if CHAR_DATA is not "Expanded") int offsetCellData = 24 + NumChars * 8 + NumChars; for (int i = 0; i < NumTiles; ++i) { for (int j = 0; j < TileWidth * TileHeight; ++j) { Tiles[i].CharData.SetU16At(j * 2, Data.UInt16At(offsetCellData + i * TileWidth * TileHeight * 2 + j * 2)); } } } // CELL_ATTRIBS. Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes (exists for ALL modes) int offsetCellAttribs = 24 + NumChars * 8 + NumChars; if (!isExpanded) { offsetCellAttribs += NumTiles * TileWidth * TileHeight * 2; } for (int i = 0; i < NumTiles; ++i) { for (int y = 0; y < TileHeight; ++y) { for (int x = 0; x < TileWidth; ++x) { if (TileColorMode == ColorMode.PER_TILE_CELL) { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight) & 0x0f)); } else { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)CustomColor); } } } } // TILE_ATTRIBS. Size = NUM_TILES bytes (1 byte per tile = "RAM colour". only exists if COLOR_MODE = 1 (Per Tile) int offsetTileAttribs = offsetCellAttribs + NumTiles * TileWidth * TileHeight; if (TileColorMode == ColorMode.PER_TILE) { for (int i = 0; i < NumTiles; ++i) { for (int y = 0; y < TileHeight; ++y) { for (int x = 0; x < TileWidth; ++x) { Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetTileAttribs + i) & 0x0f)); } } } } /* * if ( TileColorMode == ColorMode.PER_TILE_CELL ) * { * for ( int i = 0; i < NumTiles; ++i ) * { * for ( int y = 0; y < TileHeight; ++y ) * { * for ( int x = 0; x < TileWidth; ++x ) * { * Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight ) & 0x0f ) ); * } * } * } * }*/ // MAP_DATA. Size = MAP_WID x MAP_HEI bytes. int offsetMapData = offsetTileAttribs; if (TileColorMode == ColorMode.PER_TILE) { offsetMapData += NumTiles; } MapData = Data.SubBuffer(offsetMapData, MapWidth * MapHeight); return(true); }