private void Run(string[] args) { var serviceResolver = new ServiceResolver(); var logger = serviceResolver.GetService <ILogger>(); if (args.Length == 0) { Console.WriteLine("Usage: MBBSDatabase [view|convert] [files]"); } var convert = (args[0] == "convert"); foreach (string s in args.Skip(1)) { BtrieveFile file = new BtrieveFile(); try { file.LoadFile(logger, s); if (convert) { using var processor = new BtrieveFileProcessor(); processor.CreateSqliteDB(Path.ChangeExtension(s, ".DB"), file); } } catch (Exception e) { logger.Error(e, $"Failed to load Btrieve file {s}: {e.Message}\n{e.StackTrace}"); } } }
public BtrieveFileSpec(BtrieveFileProcessor db) { record_length = (ushort)db.RecordLength; page_size = (ushort)db.PageLength; number_of_keys = (ushort)db.Keys.Count; number_of_records = (uint)db.GetRecordCount(); flags = db.VariableLengthRecords ? (ushort)0x1 : (ushort)0x0; reserved = 0; unused_pages = 0; }
/// <summary> /// Sets the current btrieve file (BB value) based on btrieveFile /// </summary> protected void AllocateBB(BtrieveFile btrieveFile, ushort maxRecordLength) { var btrieve = new BtrieveFileProcessor() { FullPath = Path.Combine(mbbsModule.ModulePath, btrieveFile.FileName) }; var connectionString = "Data Source=acs.db;Mode=Memory"; btrieve.CreateSqliteDBWithConnectionString(connectionString, btrieveFile); majorbbs.AllocateBB(btrieve, maxRecordLength, Path.GetFileName(btrieve.FullPath)); }
/// <summary> /// Sets the current btrieve file (BB value) based on btrieveFile /// </summary> protected void AllocateBB(BtrieveFile btrieveFile, ushort maxRecordLength) { var btrieve = new BtrieveFileProcessor() { FullPath = Path.Combine(mbbsModule.ModulePath, btrieveFile.FileName) }; var connectionString = BtrieveFileProcessor.GetDefaultConnectionStringBuilder("acs.db"); connectionString.Mode = SqliteOpenMode.Memory; btrieve.CreateSqliteDBWithConnectionString(connectionString, btrieveFile); majorbbs.AllocateBB(btrieve, maxRecordLength, Path.GetFileName(btrieve.FullPath)); }
/// <summary> /// Generates a Real Mode Interrupt from Protected Mode /// /// Allows for calling/passing information to TSR's running in real mode. This is used by some MajorBBS modules /// for directly accessing the Btrieve Driver /// </summary> private void DosRealIntr() { var interruptNumber = GetParameter(0); var registerPointer = GetParameterPointer(1); var reserved = GetParameter(3); //Must Be Zero var wordCount = GetParameter(4); //Count of word arguments on stack var regs = new Regs16Struct(Module.Memory.GetArray(registerPointer, Regs16Struct.Size).ToArray()); switch (interruptNumber) { case 0x21: //INT 21h Call switch (regs.AX >> 8) //INT 21h Function { case 0x35: //Get Interrupt Vector { switch ((byte)(regs.AX & 0xFF)) { case 0x7B: //Btrieve Vector { //Modules will use this vector to see if Btrieve is running regs.BX = 0x33; break; } default: throw new Exception($"Unknown Interrupt Vector: {(byte)(regs.AX & 0xFF):X2}h"); } break; } default: throw new Exception($"Unknown INT 21h Function: {regs.AX >> 8:X2}h"); } break; case 0x7B: //Btrieve Interrupt { var btvda = new BtvdatStruct(Module.Memory.GetArray(regs.DS, 0, BtvdatStruct.Size)); switch ((EnumBtrieveOperationCodes)btvda.funcno) { case EnumBtrieveOperationCodes.Open: { //Get the File Name to oPen var fileName = Encoding.ASCII.GetString(Module.Memory.GetString(btvda.keyseg, 0, true)); var btvFile = new BtrieveFileProcessor(_fileFinder, Module.ModulePath, fileName, _configuration.BtrieveCacheSize); //Setup Pointers var btvFileStructPointer = new FarPtr(btvda.posblkseg, btvda.posblkoff); var btvFileNamePointer = Module.Memory.AllocateVariable($"{fileName}-NAME", (ushort)(fileName.Length + 1)); var btvDataPointer = Module.Memory.AllocateVariable($"{fileName}-RECORD", (ushort)btvFile.RecordLength); var newBtvStruct = new BtvFileStruct { filenam = btvFileNamePointer, reclen = (ushort)btvFile.RecordLength, data = btvDataPointer }; BtrieveSaveProcessor(btvFileStructPointer, btvFile); Module.Memory.SetArray(btvFileStructPointer, newBtvStruct.Data); Module.Memory.SetArray(btvFileNamePointer, Encoding.ASCII.GetBytes(fileName + '\0')); //Set the active Btrieve file (BB) to the now open file Module.Memory.SetPointer("BB", btvFileStructPointer); #if DEBUG _logger.Debug($"({Module.ModuleIdentifier}) Opened file {fileName} and allocated it to {btvFileStructPointer}"); #endif Registers.AX = 0; break; } case EnumBtrieveOperationCodes.Stat: { var currentBtrieveFile = BtrieveGetProcessor(Module.Memory.GetPointer("BB")); var btvStats = new BtvstatfbStruct { fs = new BtvfilespecStruct() { numofr = (uint)currentBtrieveFile.GetRecordCount(), numofx = (ushort)currentBtrieveFile.Keys.Count, pagsiz = (ushort)currentBtrieveFile.PageLength, reclen = (ushort)currentBtrieveFile.RecordLength } }; var definedKeys = currentBtrieveFile.Keys.Values.SelectMany(k => k.Segments).Select(k => new BtvkeyspecStruct() { flags = (ushort)k.Attributes, keylen = k.Length, keypos = k.Position, numofk = k.Number }).ToList(); btvStats.keyspec = definedKeys.ToArray(); Module.Memory.SetArray(btvda.databufsegment, btvda.databufoffset, btvStats.Data); Registers.AX = 0; break; } case EnumBtrieveOperationCodes.SetOwner: //Ignore Registers.AX = 0; break; default: throw new Exception($"({Module.ModuleIdentifier}) Unknown Btrieve Operation: {(EnumBtrieveOperationCodes)btvda.funcno}"); } break; } default: throw new Exception($"({Module.ModuleIdentifier}) Unhandled Interrupt: {interruptNumber:X2}h"); } Module.Memory.SetArray(registerPointer, regs.Data); }