Announcement

Collapse
No announcement yet.

Wer kan mir helfen diese MS C++ Funktion in Delphi5 zu uebersetzen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Wer kan mir helfen diese MS C++ Funktion in Delphi5 zu uebersetzen

    <font face="Arial">
    Hi,<br>
    wer kan mir helfen diese MS C++ Funktion in Delphi5 zu uebersetzen?<br>
    <br>
    Danke<br>
    <br>
    Gru&szlig;<br>
    Harald Binder<br>
    <br>
    <br>
    #define ICB_ADJUSTBUFFER4K(_st_, _st4k_, _si_, _si4k_) \<br>
    { \<br>
    ..if(((long)_st_ &amp; 0x0FFF) != 0) \<br>
    ..{ \<br>
    ....long _sa_ = (long)_st_; \<br>
    ....long _pd_ = _sa_ &amp; 0x00000FFF; \<br>
    ...._sa_ &amp;= 0xFFFFF000; \<br>
    ...._sa_ += 0x00001000; \<br>
    ...._pd_ = 0x00001000 - _pd_; \<br>
    ....if(_si4k_ != NULL) \<br>
    ......*_si4k_ = _si_ - _pd_; \<br>
    ....if(_st4k_ != NULL) \<br>
    ......*_st4k_ = (void*)_sa_; \<br>
    ..} \<br>
    ..else \<br>
    ..{ \<br>
    ....if(_si4k_ != NULL) \<br>
    ......*_si4k_ = _si_; \<br>
    ....if(_st4k_ != NULL) \<br>
    ......*_st4k_ = (void*)_st_; \<br>
    ..} \<br>
    }<br>
    <br>
    <br>
    ..- Speicherallokierung f&uuml;r die Aufnahme:<br>
    ....Die Startadresse der allokierten Speicherbl&ouml;cke, die f&uuml;r die Aufnahme<br>
    ....verwendet werden (mit icb_PrepareBuffer()), m&uuml;ssen durch 4096 teilbar<br>
    ....sein (Page aligned) !!! Ist dies nicht der Fall k&ouml;nnen durch den<br>
    ....DMA Chip fremde Speicherbreiche &uuml;berschrieben werden, was u.U. zu<br>
    ....Abst&uuml;rzen bis zum BlueScreen f&uuml;hrt. Das Macro ICB_ADJUSTBUFFER4K der<br>
    ....piranha.h kann zum Korrigieren der Startadresse und Blockgr&ouml;&szlig;e<br>
    ....verwendet werden:<br>
    <br>
    ....Verwendung des Konvertierungsmacros ICB_ADJUSTBUFFER4K<br>
    ....(definiert in piranha.h):<br>
    <br>
    ....Bsp. 1:<br>
    <br>
    .....long size = 32768;<br>
    .....char* start = 0xE000A960;<br>
    <br>
    .....ICB_ADJUSTBUFFER4K((void*)start, (void**)&amp;start, size, &amp;size);<br>
    <br>
    .....Ergebnis: size = 31072;<br>
    ................start = E000B000;<br>
    <br>
    ....Bsp. 2:<br>
    <br>
    ......long size = 32768;<br>
    ......char* start = 0xE000A960;<br>
    ......long size4k;<br>
    ......char* start4k;<br>
    <br>
    ......ICB_ADJUSTBUFFER4K((void*)start, (void**)&amp;start4k, size, &amp;size4k);<br>
    <br>
    ......Ergebnis: size = 32768;<br>
    .................start = 0xE000A960;<br>
    .................size4k = 31072;<br>
    .................start4k = E000B000;<br>
    <br>
    <br>
    ....WICHTIG:<br>
    .....Falls die Originalwerte noch ben&ouml;tigt werden (z.B. zum Freigeben<br>
    .....des Speicherblocks), so m&uuml;ssen diese gespeichert werden (wie in Bsp. 2)<br>
    </font>

  • #2
    Hi

    Um die Speicherung etc. mußt Du Dich kümmern.

    <pre>

    function Adjust4K(P: Pointer): Pointer;
    begin
    Result := nil;
    if (P <> nil) and (Integer(P) and $0FFF <> 0) then
    Result := (PChar(P) + $0FFF) and not $0FFF;
    end;

    </pre>

    Das justiert immer aufwärts, rundet also immer auf $1000 (4k) Grenzen.
    Auch bei der Allozierung des Pointers mit GetMem() etc. mußt Du darauf achten IMMER die Größe mit $0FFF Bytes größer zu veranlagen.

    Gruß Hage

    Comment


    • #3
      Hi

      Nochwas, günstig für Dich: Du solltest den eigentlichen Pointer als Struktur definieren.

      <pre>

      type
      T4KPtr = packed record
      Ptr: Pointer;
      Size: Integer;
      4kPtr: Pointer;
      end;

      var
      4KPtr: T4KPtr;
      begin
      4KPtr.Size := $1000 + $0FFF;
      4KPtr.Ptr := AllocMem(4KPtr.Size);
      4KPtr.4kPtr := PChar(4KPtr.Ptr) + $0FFF and not $0FFFF;
      .... weiter wird mit .4kPtr gearbeitet
      end;

      </Pre>

      Gruß Hage

      Comment


      • #4
        Hi

        Oder, Du nutzt diese beiden Funktionen (dachte ich könnte sie vielleicht selber mal gebrauchen. Diese allozieren einen "ausgerichteten" Zeiger /Speicherblock und geben diesen auch wieder frei. ALLES vollständig transparent für den User. Im ungünstigsten Fall werden genau Align + 8 Bytes zuviel für einen Block alloziert, ist aber rel. unwahrscheinlich. Im Gegensatz zu obigen funktionen, kann diese Funktion auch z.B. auf einer 13 Byte Grenze ausrichten, Align kann also JEDEN wert annehmen.

        <pre>

        procedure GetMemAlign(var P: Pointer; Size, Align: Cardinal);
        var
        S: Pointer;
        I: Cardinal;
        begin
        P := nil;
        if Size = 0 then Exit;
        // allocated overestimated memory
        GetMem(S, (Size + Align -1) div Align * Align + SizeOf(Integer) * 2 + Align);
        // calculate aligned memoryaddress
        P := PChar(Cardinal(PChar(S) + Align -1) div Align * Align);
        // check iff P and S are good aligned, but bad for us
        if P = S then Inc(PChar(P), Align);
        // calulate relative offset to aligned memoryaddress
        I := PChar(P) - PChar(S);
        // check iff enough space to store 2 Integers
        if I >= SizeOf(Integer) * 2 then
        begin
        // calculate real used memorysize
        Inc(I, Size);
        // Free rest of unused space after (P + Size)
        ReallocMem(S, I);
        // store fields, before P, first Size of complete Block
        Dec(PChar(P), SizeOf(Integer));
        Integer(P^) := I;
        // next, real Memoryaddress of complete Block
        Dec(PChar(P), SizeOf(Integer));
        Pointer(P^) := S;
        // restore P to align address
        Inc(PChar(P), SizeOf(Integer) * 2);
        // I - Size = overallocated memoryspace
        end else
        // should be never raise
        raise Exception.Create('error');
        end;

        procedure FreeMemAlign(var P: Pointer);
        var
        Size: Cardinal;
        begin
        if P = nil then Exit;
        // first give size of complete Block
        Dec(PChar(P), SizeOf(Integer));
        Size := Integer(P^);
        // next give original Address of complete Block
        Dec(PChar(P), SizeOf(Integer));
        P := Pointer(P^);
        // now, free the complete Block
        FreeMem(P, Size);
        end;

        Nutzung:

        var
        P: Pointer;
        begin
        GetMemAlign(P, 4096, $1000);
        try
        finally
        FreeMemAlign(P);
        end;
        end;

        </pre>

        Gruß Hage

        Comment


        • #5
          Hi Hagen.<br>
          Ja ich muß den Speicher selber anlegen. dieser Speicher wird von einer Videokarten mit Bilddaten gefüllt.<br><br>
          Danke für dein Hilfe. Mit dem was du mir so geschrieben hast,<br> kann ich ein gutes Stück weiterkommen.<br>
          <br>
          Gruß<br>
          Harald Binde

          Comment


          • #6
            Hi

            Per DMA ? Ich weiß nicht ob Du da einfachen "virtuellen" Delphi Speicher nutzen kannst. Früher, unter DOS, als ich die DMA Controller für die Soundblaster programmierte, konnte man nur ausgewählte Adressen nutzen. Diese mussten im unteren 640K Segment auf 4096 Bytes ausgereichtet werden, da der normale DMA nur 12 Bit Adressregister hat. Dies bedeutet aber auch das die PHYSIKALISCHE Speicheradresse unterhalb von 640K liegen muß. Ich weiß leider nicht wie's in Windows aussieht, die Hardware (DMA Controller) habe sich aber NICHT geändert.

            Gruß Hage

            Comment


            • #7
              <font face="Arial">
              Hi&nbsp;Hagen,<br>
              der&nbsp;Buffer&nbsp;wird&nbsp;wie&nbsp;folgt&nbsp ;angelegt:<br>
              <br>
              &nbsp;var<br>
              &nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;:&nbsp;HGLOBAL;< br>
              &nbsp;&nbsp;&nbsp;&nbsp;pb&nbsp;:&nbsp;Pointer;<br >
              <br>
              &nbsp;begin<br>
              &nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;:=&nbsp;GlobalAlloc (GMEM_MOVEABLE,&nbsp;Buf[BufferNr].hMem);<br>
              &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;h&nbsp;&lt;&gt;&nb sp;0&nbsp;then&nbsp;begin<br>
              &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;try&nbsp;to&nbsp;lock&nbsp;the&nbsp;buffer&n bsp;in&nbsp;memory&nbsp;(MUST&nbsp;be&nbsp;done&nb sp;!!!)<br>
              &nbsp;&nbsp;&nbsp;&nbsp;pb&nbsp;:=&nbsp;GlobalLock (h);<br>
              &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;pb&nbsp;=&nbsp;nil &nbsp;then&nbsp;begin<br>
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GlobalFree(h); <br>
              &nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;else&nbsp;begin<b r>
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;........ ..<br>
              PS<br>
              &nbsp;&nbsp;&nbsp;Wenn&nbsp;Du&nbsp;dich&nbsp;auch &nbsp;mit&nbsp;Threads&nbsp;und&nbsp;Events&nbsp;a uskennst,<br>
              &nbsp;&nbsp;&nbsp;den&nbsp;Schau&nbsp;doch&nbsp;bi tte&nbsp;mal&nbsp;unter&nbsp;Threads&nbsp;nach.<br >
              &nbsp;&nbsp;&nbsp;Da&nbsp;habe&nbsp;ich&nbsp;auch& nbsp;noch&nbsp;ein&nbsp;Problem.<br>
              <br>
              Gru&szlig;<br>
              Harald&nbsp;Binder<br>
              </font&gt

              Comment


              • #8
                Hi

                Ob, Du GloablAlloc/LocalAlloc/VirtualAlloc oder Delphi's GetMem() etc. nutzt, ALLES gibt Dir virtuellen Speicher oberhalb 640K zurück !!
                Wie gesagt, ich kenne Dein Problem nicht genau genug, z.b. Hardwaredocus usw. Willst Du etwa den DMA Controller selber programmieren ? Unter Windows ? Hoffentlich doch nicht für eine Software die Du dann verkaufst, oder

                Gruß Hage

                Comment

                Working...
                X