⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jdev_main.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 3 页
字号:

  if Assigned(dwarf) then dwarf.Free;  dwarf := nil;
  if Assigned(elf) then elf.Free;      elf := nil;

  try
    // Load the file into the core
    stream := TFileStream.Create(filename, fmOpenRead or fmShareDenyNone);
    case typ of
      ftROM: begin
        GetMem(data, stream.size);
        stream.Read(data^, stream.size);
        vmInsertCartridge(data, stream.size);
        FreeMem(data, stream.size);

        cartLoaded := true;
        stream.Free;
      end;
      ftMultiboot: begin
        vmLockMemory(banks);
        stream.Read(banks.exwram^, Min(stream.size, $40000));
        banks.wram^[$7FFA] := 1;
        vmUnlockMemory(banks);
        stream.Free;
      end;
      ftELF: begin
        cartLoaded := true;

        // Create and build an elf class out of the file
        elf := TELFFile.Create(stream);
        elf.Build;

        // Flatten the elf into a binary
        size := elf.Flatten(data);
        vmInsertCartridge(data, size);

        dwarf := ProcessDWARF(elf, ExtractFilePath(filename));
        stream.Free;
      end;
      ftSaveState: LoadSavestate(filename, stream);
    else
      stream.Free;
    end;

    ReassertBreakpoints;
  except on
    e: Exception do begin
      logWriteLn('Error: ' + e.Message);
      e.Free;
    end;
  end;

  // Reset user interface stuff
  isActive := autorunROMs;
  fps := 0;

  lastRomFilename := filename;
  if typ <> ftSavestate then begin
    vmReset;
    LoadCartInfo;

    if typ = ftMultiboot then begin
      vmSetRegister(r15, $02000000)
    end else
      if autopatchLogo then PatchHeader;
  end;

  // Update the observer display
  if mruList.IndexOf(lastRomFilename) = -1 then begin
    mruList.Insert(0, lastRomFilename);
    if mruList.Count > 10 then mruList.Delete(10);
    RebuildMRUList;
  end;
  Caption := 'Mappy VM [' + ExtractFileName(lastROMFilename) + ']';
  UpdateObservers;

  // Initialize the file watcher
  lastFileAge := FileAge(filename);
  fileWatcher.Directory := ExtractFilePath(filename);
  fileWatcher.Start;

  Result := true;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.clockTimer(Sender: TObject);
begin
//
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.OnIdle(Sender: TObject; var Done: Boolean);
var
  cycles, delta: integer;
  token: TvmProfileToken;
  t0, tslf: uint32;
begin
  Done := true;
  
  if clockMutex then Exit;
  if not coreLoaded then Exit;
  clockMutex := true;

  timeBeginPeriod(1);
  tslf := timeGetTime;

  repeat
    if isActive then begin
      // If we're meant to do automatic updates, and there is a rom loaded, then lets rock

      // Start the fps processing
      token := vmStartProfile;
      vmRenderFrame;
      cycles := vmStopProfile(token);
      ExecuteCleanup;
      UpdateObservers;
      repeat until timeGetTime-tslf > msBetweenFrames;

      // Update the framerate
      t0 := timeGetTime;
      delta := t0-tslf;
      tslf := t0;

      if delta <> 0 then begin
        fps := 0.95*fps + 0.05*(1000/delta)*(cycles/(1232*228));
        if sysSound.frequency > 0 then
          vmSetAudioRate(max(trunc((fps * 16777216) / (sysSound.frequency*59.727)), 64));
      end;

      if capturing then
        status.Panels[0].Text := ' Status: Capturing'
      else
        status.Panels[0].Text := ' Status: Running';

      status.Panels[1].Text := Format(' FPS: %.1f (%.0f%% optimal)', [fps, 100*fps/59.727])
    end else begin
      status.Panels[0].Text := ' Status: Paused';
      if Copy(status.Panels[1].Text, 1, 4) = ' FPS' then status.Panels[1].Text := '';
    end;

    sysSound.enabled := isActive and appFocused and mToggleSoundEnabled.Checked;
    Application.ProcessMessages;
  until Application.Terminated or not isActive;
  timeEndPeriod(1);

  clockMutex := false;
end;

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

procedure TjdevMain.LoadCore(filename: string);
var
  i: integer;
  ini: TIniFile;
  item: TMenuItem;
  st: string;
  ws: TWindowState;
begin
  ini := TIniFile.Create(appIniFile);

  vmLoadCore(PChar(filename));

  // Video Setup
  InitVideo;
  vmSetOnVideo(OnVideoReady);
  vmSetOnConsole(OnConsoleReady);

  ws := TWindowState(Min(2, Max(0, ini.ReadInteger('Video Options', 'WindowState', Ord(wsNormal)))));
  if ws <> wsMaximized then begin
    ClientWidth := ini.ReadInteger('Video Options', 'ScreenWidth', 240);
    ClientHeight := status.height + ini.ReadInteger('Video Options', 'ScreenHeight', 160);
    Left := ini.ReadInteger('Video Options', 'Left', Left);
    Top := ini.ReadInteger('Video Options', 'Top', Top);
  end else begin
    ClientWidth := 240;
    ClientHeight := status.height + 160;
  end;
  WindowState := ws;

  LoadVideoOptions(ini);

  // Audio Setup
  sysSound := TDirectSoundDriver.Create;
  LoadAudioOptions(ini);
  sysSound.Available := true;

  // Joypad Setup
  LoadJoypadOptions(ini);

  // Debug Setup
  LoadDebugOptions(ini);

  // General Setup
  LoadGeneralOptions(ini);

  // Reset the CPU
  vmReset;

  // Filenames
  lastRomFilename := ini.ReadString('Filenames', 'LastImage', '');
  lastScreenshotFilename := ini.ReadString('Filenames', 'LastScreenshot', '');
  if not FileExists(lastRomFilename) then lastRomFilename := '';
  if not FileExists(lastScreenshotFilename) then lastScreenshotFilename := '';

  mruList.Clear;
  for i := 0 to 9 do begin
    st := ini.ReadString('Filenames', 'Recent' + IntToStr(i), '');
    if FileExists(st) then mruList.Insert(i, st);
  end;
  RebuildMRUList;

  // Open any previously opened viewers
  for i := 0 to menuViewers.Count - 1 do begin
    item := TMenuItem(menuViewers.Items[i]);
    if ini.ReadBool(StripHotKey(item.Caption), 'Opened', false) then
      CreateObserver(StripHotKey(item.Caption), item);
  end;

  // Close the .INI file
  ini.Free;

  Application.OnActivate := OnActivateApp;
  Application.OnDeactivate := OnDeactivateApp;
  Application.OnIdle := OnIdle;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.UnloadCore;
var
  ini: TIniFile;
  i: integer;
  st: string;
begin
  ini := TIniFile.Create(appIniFile);

  // Video Setup
  vmSetOnVideo(nil);
  SaveVideoOptions(ini);
  FreeVideo;

  ini.WriteInteger('Video Options', 'WindowState', Ord(WindowState));
  ini.WriteInteger('Video Options', 'ScreenWidth', ClientWidth);
  ini.WriteInteger('Video Options', 'ScreenHeight', ClientHeight - status.height);
  ini.WriteInteger('Video Options', 'Left', Left);
  ini.WriteInteger('Video Options', 'Top', Top);

  // Audio Setup
  SaveAudioOptions(ini);
  sysSound.Free;

  // Joypad Setup
  SaveJoypadOptions(ini);

  // Debug Setup
  SaveDebugOptions(ini);

  // General Setup
  SaveGeneralOptions(ini);

  // Observers
  for i := 0 to menuViewers.Count - 1 do begin
    st := StripHotKey(TMenuItem(menuViewers.Items[i]).Caption);
    ini.WriteBool(st, 'Opened', FindObserver(st) <> nil);
  end;

  // Filenames
  ini.WriteString('Filenames', 'LastImage', lastRomFilename);
  ini.WriteString('Filenames', 'LastScreenshot', lastScreenshotFilename);
  for i := 0 to 9 do begin
    if i < mruList.Count then st := mruList.Strings[i] else st := '';
    ini.WriteString('Filenames', 'Recent' + IntToStr(i), st);
  end;
  mruList.Clear;
  RebuildMRUList;

  CloseObservers;

  // Unload the core
  vmSetOnConsole(nil);
  vmUnloadCore;

  ini.Free;

  Application.OnActivate := nil;
  Application.OnDeactivate := nil;
  Application.OnIdle := nil;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.LoadCartInfo;
var
  size: integer;
  data: PByteArray;
  stream: TFileStream;
  name: string;
  banks: TvmMemoryLock1;
begin
  name := ChangeFileExt(lastRomFilename, '.sav');
  if FileExists(name) then begin
    logWriteLn('Loading cartridge info from ' + ExtractFileName(name));

    stream := TFileStream.Create(name, fmOpenRead or fmShareDenyNone);
    size := stream.Size;
    GetMem(data, size);
    stream.Read(data^, size);

    vmLockMemory(banks);
    vmSetCartInfo(size, data);
    vmUnlockMemory(banks);

    FreeMem(data, size);
    stream.Free;
  end;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.SaveCartInfo;
var
  size: integer;
  data: pointer;
  stream: TFileStream;
  name: string;
begin
  size := vmGetCartInfo(nil);
  if size > 0 then begin
    name := ChangeFileExt(lastRomFilename, '.sav');
    logWriteLn('Saving cartridge info to ' + ExtractFileName(name));

    GetMem(data, size);
    vmGetCartInfo(data);

    stream := TFileStream.Create(name, fmCreate);
    stream.Write(data^, size);
    stream.Free;

    FreeMem(data, size);
  end;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.mNothingnessClick(Sender: TObject);
var
  list: TStringList;
  i: integer;
begin
  Beep;

  list := TStringList.Create;

  SaveTranslation(self, list);
  for i := 0 to observerList.count - 1 do
    SaveTranslation((observerList.Items[i] as TCpuObserver), list);
  SaveTranslation(jdevModify, list);
  SaveTranslation(jdevDisasmDialog, list);
  SaveTranslation(jdevCaptureForm, list);
  SaveTranslation(dbgFindPattern, list);

  list.SaveToFile(ExtractFilePath(ParamStr(0)) + 'American English.trs');
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.LoadNewCore(Sender: TObject);
begin
  openDialog.Filter := 'Mappy VM Cores|*.core|All files|*.*';
  openDialog.DefaultExt := 'core';
  openDialog.FileName := ExtractFilePath(ParamStr(0)) + 'core\standard.core';
  if openDialog.Execute then
    if FileExists(openDialog.Filename) then begin
      UnloadCore;
      LoadCore(openDialog.Filename);
    end;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.SaveSavestate(Sender: TObject);
var
  size: integer;
  save: PvmSavestate;
  stream: TFileStream;
  st: string;
begin
  saveDialog.Filter := 'Maypy VM Savestates|*.jst|All files|*.*';
  saveDialog.filename := ChangeFileExt(lastRomFilename, '.jst');
  saveDialog.DefaultExt := 'jst';
  if saveDialog.Execute then begin
    size := vmSaveState(nil);
    if size > 0 then begin
      GetMem(save, size);
      vmSaveState(save);

      if save^.cartLoaded then begin
        st := ExtractFileName(lastRomFilename);
        if st <> '' then begin
          Move(st[1], save^.filename, Min(Length(st), 255));
          save^.filename[Min(Length(st), 255)] := #0;
          save^.crc := CrcROM;
        end;
      end;

      stream := TFileStream.Create(saveDialog.Filename, fmCreate);
      stream.Write(save^, size);
      stream.Free;

      FreeMem(save, size);
    end;
  end;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.DwarfDebugger1Click(Sender: TObject);
begin
  jdevDwarfDebug.Show;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.RebuildMRUList;
var
  i: integer;
begin
  mReopenFile.Clear;
  for i := 0 to mruList.Count - 1 do begin
    mReopenFile.Add(NewItem(mruList.Strings[i], 0, false, true, LoadRecent, i, 'mruitem'+IntToStr(i)));
  end;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.RebuildPluginList;
var
  i: integer;
  plugin: PvmPluginHeader;
  item: TMenuItem;
begin
  for i := 0 to plugins.Count - 1 do begin
    plugin := @(TPlugin(plugins.items[i]).header);
    item := NewItem(plugin^.triggerCaption, 0, false, true, OnTriggerPluginClick, i, 'triggerPlugin'+IntToStr(i));
    item.Tag := i;
    mTools.Add(item);
  end;
end;

//////////////////////////////////////////////////////////////////////

procedure TjdevMain.OnTriggerPluginClick(Sender: TObject);
begin
  TriggerPlugin(TMenuItem(Sender).Tag);
end;

//////////////////////////////////////////////////////////////////////

initialization
  msBetweenFrames := 0;
end.

//////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -