  var _crash_details: WideString;
  procedure CheckForGenericDyingYells(skip_frames: integer = 0);
  var a, ca: pointer; i, sf: integer; w: WideString; csstarted: boolean = false;
  begin
    Try
//addlog('--- CheckForGenericDyingYells called');
      if not MotherState^.NowDying and (((ExceptObject <> nil) and ExceptObjectisException()) or (SafeCallExceptionCaught))
      then begin
        if SafeCallExceptionCaught then begin
          skip_frames+= 1;
          _crash_details:= '';
        end
        else
          _crash_details:=TellException(ExceptObject as Exception);
        if _crash_details <> '' then _dyell += #10#13#10#13 + _crash_details;
        MotherState^.DyingAfterTrueException:= True;
//addlog('--- _dyell = %0', [_dyell]);
        //_dyell + #10#13#10#13 + AnsiToWide((ExceptObject as Exception).Message);//
      {$ifdef win32}
        //..������� ������������ ���������
        //  ������� WinAPI GetLastEror (� ������� Win32LastEror)
       // _dyell:= _dyell + Win32LastError;
      {$endif}
        if not MotherState^.CallStackLogged then begin
          MotherState^.CallStackLogged:= Yes;
          _crash_details:= '';
          i:= 0;
          a:= get_frame;
          while Assigned(a) do begin
            ca:= get_caller_addr(a);
            {ignore the first two callers. These always are: 0). call to this
              procedure from Die() or TryWrap() and 1). Call to Die itself from the
              except... block}
            if Assigned(ca) then begin
              w:= ShortExpAddr(ca);
              if (pos('mo_hub_die.inc', w) = 0) and (pos('cl_die.inc', w) = 0) and (pos('mo_die1.inc', w) = 0) and (pos('cl_seh_hack.pp', w) = 0) then begin
                //a dirty trick. I was using 'first N frames' at first, but that is too bothersome.
                //I just moved all dying stuff into an include and check for its name reported by lineinfo
                //if i = (2 + skip_frames) then
                if not csstarted then begin
                  csstarted:= true;
                  _crash_details+= #10#13'Call stack:';
                end;
                //if i >= (2 + skip_frames) then
                _crash_details+= #10#13'  ' + w; //ShortExpAddr(ca);
              end;
              inc(i);
            end
            else Break;
            if i> MAX_STACK_FRAMES_DUMP then break;
            a:= get_caller_frame(a);
          end;
          with MotherState^ do begin
            if DeveloperMode or DebugMode
              then _dyell+= #10#13#10#13 + _crash_Details;
            //CallStackLogged:= Yes;
          end;
        end;
      end;
      {$ifdef win32}
      //  SetLastError(0);
      {$endif}
      if MotherState^.DebugMode then AddLog(_dyell);
    Except
      _dyell:=_dyell + #10#13'!Crashed accessing Exception object!';
    End;
    SafeCallExceptionCaught:= false;
  end;

  var GenericDyingYellsLogged: boolean = false;

  function ExplainCallStack(steps_to_ignore: integer; max_steps: integer): WideString;
  var
    a, ca: pointer;
    i: integer;
    csstarted: boolean = false;
    w: WideString;
  begin
    Result:= 'Call stack: not available.';
    i:=0;
    a:= get_frame;
    while Assigned(a) do begin
      ca:= get_caller_addr(a);
      {ignore the first two callers. These always are: 0). call to this
        procedure from Die() or TryWrap() and 1). Call to Die itself from the
        except... block}
      if Assigned(ca) then begin
        w:= ShortExpAddr(ca);
        if (pos('mo_hub_die.inc', w) = 0) and (pos('cl_die.inc', w) = 0) and (pos('mo_die1.inc', w) = 0) and (pos('cl_seh_hack.pp', w) = 0) then begin
          if not csstarted then begin
            csstarted:= true;
            Result:= 'Call stack:';
          end;
          Result+= #10#13'  ' + w;
        end;
        inc(i);
      end
      else Break;
      if i > max_steps + steps_to_ignore then break;
      a:= get_caller_frame(a);
    end;

  end;

  procedure SehHackCheckForGenericDyingYells();
  var
    a, ca: pointer; i: integer;
    csstarted: boolean = false;
    w: WideString;
  begin
    try
      if not MotherState^.NowDying
      then begin
        MotherState^.DyingAfterTrueException:= True;
        if not MotherState^.CallStackLogged then begin
          _crash_details:= '';
          i:=0;
          a:= get_frame;
          while Assigned(a) do begin
            ca:= get_caller_addr(a);
            {ignore the first two callers. These always are: 0). call to this
              procedure from Die() or TryWrap() and 1). Call to Die itself from the
              except... block}
            if Assigned(ca) then begin
              //if i = 3 then _crash_details+= #10#13'Call stack:';
              //if i >= 3 then _crash_details+= #10#13'  ' + ShortExpAddr(ca);
              w:= ShortExpAddr(ca);
              if (pos('mo_hub_die.inc', w) = 0) and (pos('cl_die.inc', w) = 0) and (pos('mo_die1.inc', w) = 0) and (pos('cl_seh_hack.pp', w) = 0) then begin
                if not csstarted then begin
                  csstarted:= true;
                  _crash_details+= #10#13'Call stack:';
                end;
                _crash_details+= #10#13'  ' + w;
              end;
              inc(i);
            end
            else Break;
            if i> MAX_STACK_FRAMES_DUMP then break;
            a:= get_caller_frame(a);
          end;
          with MotherState^ do begin
            if DeveloperMode or DebugMode
              then _dyell+= #10#13#10#13 + _crash_Details;
            CallStackLogged:= Yes;
          end;
        end;
      end;
    except
      _dyell:=_dyell + #10#13'!Crashed gathering Exception details!';
    end;
  end;


procedure DieBySEhHack;
begin
  {$ifdef buildmein}
  _dyell:= 'This shouldn''t be happening!';
  {$else}
  _dyell:= RuEn('Системное исключение: ','System exception: ')
    + SehNameByCode(MotherState^.sehh_ExceptionCode)
    + #10#13'  ' + SehHackTellExceptionAddress(MotherState^.sehh_ExceptionAddress);
//    MotherState^.sehh_ExceptionCode := 0; //чтобы мессага не двоилась
  {$endif}
  SehHackCheckForGenericDyingYells;
  _HostDyellW(PWideChar(_dyell));
  with MotherState^ do
    if not DeveloperMode and not DebugMode and not GenericDyingYellsLogged
      then AddLog('%0'#10#13'<---------------------->',[_crash_Details]);
  MotherState^.NowDying:= Yes;  //SetDying(yes);
  GenericDyingYellsLogged:= Yes;
  raise exception.create('');

end;


Procedure DieSilently;
begin
  SetDying(yes);
  raise exception.create('');
end;


Procedure Die(YellID :TMessageID; Param: array of const);
begin
  _dyell:=MsgFormat(YellID, Param);
  {$ifdef windows}
    if MotherState^.MainThreadId <> GetCurrentThreadId() then begin
      ThreadManager.PassDying(_dyell);
      Exit;
    end;
  {$else}
    {$fatal not implemented yet}
  {$endif}
  CheckForGenericDyingYells;
  _HostDyellW(PWideChar(_dyell));
  with MotherState^ do
    if not DeveloperMode and not DebugMode and not GenericDyingYellsLogged
      then AddLog('%0'#10#13'<---------------------->',[_crash_Details]);
  MotherState^.NowDying:= Yes; //SetDying(yes);
  GenericDyingYellsLogged:= Yes;
  raise exception.create('');
end;

Procedure Die(u: WideString; Param: array of const);
begin
  _dyell:=PervertedFormat(u, Param);
  {$ifdef windows}
    if MotherState^.MainThreadId <> GetCurrentThreadId() then begin
      ThreadManager.PassDying(_dyell);
      Exit;
    end;
  {$else}
    {$fatal not implemented yet}
  {$endif}
  CheckForGenericDyingYells;
  _HostDyellW(PWideChar(_dyell));
  with MotherState^ do
    if not DeveloperMode and not DebugMode and not GenericDyingYellsLogged
      then AddLog('%0'#10#13'<---------------------->',[_crash_Details]);
  MotherState^.NowDying:= Yes; //SetDying(yes);
  GenericDyingYellsLogged:= Yes;
  raise exception.create('');
end;

Procedure Die(r, e: WideString);
begin
//    Die(RuEn(r, e), []);


  _dyell:=RuEn(r, e);
  _HostDyellW(PWideChar(_dyell));

  with MotherState^ do
    if not DeveloperMode and not DebugMode and not GenericDyingYellsLogged
      then AddLog('%0'#10#13'<---------------------->',[_crash_Details]);

  MotherState^.NowDying:= Yes; //SetDying(Yes);
  GenericDyingYellsLogged:= Yes;

  raise exception.create('');

end;

Procedure Die(AnsiYell: AnsiString);
begin
  Die(AnsiToWide(AnsiYell), [])
end;

Procedure Die(YellID :TMessageID);
begin
  Die(YellId, []);
end;

Procedure Die(AnsiYell: AnsiString; param: array of const);
begin
  Die(AnsiToWide(AnsiYell), param);
end;

Procedure Die(u: WideString);
begin
  Die(u, []);
end;

procedure DieBaka(u: AnsiString);
begin
   Die(MI_ERROR_PROGRAMMER_NO_BAKA,[u]);
end;
