Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 122
» Latest member: Wolfgang Dunczewski
» Forum threads: 96
» Forum posts: 759

Full Statistics

Latest Threads
How to run PB progs in Li...
Forum: PowerBASIC for Windows
Last Post: George Bleck
5 hours ago
» Replies: 5
» Views: 142
Having problems with pbus...
Forum: This and that - friendly chat
Last Post: Stuart McLachlan
Today, 05:57 AM
» Replies: 1
» Views: 79
Very Simple Round Gauge 0...
Forum: Source Code Library
Last Post: Jules Marchildon
18.10.2025, 02:17 AM
» Replies: 6
» Views: 586
Arduino users news
Forum: This and that - friendly chat
Last Post: Pierre Bellisle
14.10.2025, 04:58 AM
» Replies: 1
» Views: 145
The Future
Forum: Suggestions and discussion about PUMP
Last Post: Dale Yarker
12.10.2025, 07:34 AM
» Replies: 84
» Views: 9,094
READ$/Data Slow
Forum: PowerBASIC for Windows
Last Post: Brent F Boshart
11.10.2025, 09:13 PM
» Replies: 4
» Views: 245
7zip alternatives ?
Forum: This and that - friendly chat
Last Post: Eric Pearson
08.10.2025, 04:07 PM
» Replies: 4
» Views: 256
Doubly Linked String/WStr...
Forum: Source Code Library
Last Post: Stanley Durham
05.10.2025, 10:19 AM
» Replies: 2
» Views: 198
DOCX and XLSX Viewer
Forum: PowerBASIC for Windows
Last Post: Dale Yarker
05.10.2025, 05:05 AM
» Replies: 9
» Views: 860
Very Simple Round Gauge D...
Forum: Programming
Last Post: Jules Marchildon
03.10.2025, 03:06 AM
» Replies: 5
» Views: 523

 
  High resolution replacement for Sleep
Posted by: David Roberts - 01.09.2025, 11:33 PM - Forum: Source Code Library - Replies (2)

SleepX()

SleepX() is a high resolution replacement for Sleep.

The principle used has an analogy with HiFi were a class B amplifier is used to get us within a neighbourhood of a desired voltage and then uses a class A amplifier to fine tune. The cost of this approach is much less than using only a class A amplifier, which are expensive.

The class B amplifier analogy uses Sleep and the class A amplifier analogy uses the Performance Counter, which has a resolution of 100ns with Windows 10 and later.

The following code has the SleepX() code and a usage example.

This is a typical output.

Code:
Quarter of a millisecond: .2503 ms

2 seconds: 2.0000003 s

Silly: 1234.0003 ms

1  1.0001 ms
2  2.0001 ms
3  3.0002 ms
4  4.0001 ms
5  5.0002 ms
6  6.0002 ms
7  7.0002 ms
8  8.0001 ms
9  9.0001 ms
10  10 ms
11  11.0002 ms
12  12.0002 ms
13  13.0001 ms
14  14.0001 ms
15  15.0001 ms
16  16.0002 ms
17  17.0002 ms
18  18.0002 ms
19  19.0002 ms
20  20.0001 ms
21  21.0003 ms
22  22.0002 ms
23  23.0001 ms
24  24.0001 ms
25  25 ms
26  26.0002 ms
27  27.0002 ms
28  28.0002 ms
29  29.0002 ms
30  30.0002 ms

The first example looks at a delay of a quarter of a millisecond. I doubt that anyone will have a use for that. The second example looks at a delay of two seconds. The third example looks at a 'silly' delay of 1234ms, The following looks at delays from 1ms to 30ms in steps of 1ms.

All the results have a sub micro accuracy inline with the Performance Counter on Windows 10 and later.

SleepX() has two parts: The first part is used for delays <= to 3ms and only polls the Performance Counter. This is expensive but is a short-lived expense and should not impact on the system performance. The second part uses the construct 'Sleep ( n-3 )' to get us within a neighbourhood of the target delay, and then we poll the Performance Counter to fine tune. 'Sleep ( n-3 )' needs a resolution of 1ms and why we use SetHiRes.

'Sleep ( n-3 )' does not use any CPU load. The CPU load only kicks in when we enter the 'class A' mode, so is an absolute value and should not impact on the system performance.

Why was 'n <= 3'.  It is reasonable to expect a 1ms resolution to give a delay of between n ms and n+1 ms. In practice, we can exceed n+1 ms and about one third of delays do just that. It is very rare, but values approaching n+1.5 ms have been seen. To mitigate that issue, 'n <= 3' was chosen.

That is it: A very simple idea to give a high resolution replacement for Sleep with a negligible CPU load.

It is worth noting that
Code:
SetHiRes
<Code to time>
RevokeHiRes
is acceptable, but it should not be used within a loop; for example a graphics application with 60, or so, fps. That will upset the system clock. It is better to use SetHiRes at the beginning of an application and RevokeHiRes when the higher resolution is no longer needed. If you forget to use RevokeHiRes SetHiRes will be cancelled when the process terminates. Microsoft neglects to mention that.

Code:
#COMPILE EXE
#DIM ALL
#INCLUDE "win32api.inc"

' SOURCE CODE:

Macro QPC = QueryPerformanceCounter qTimeNow

Macro SetHiRes
  MacroTemp Time
  Dim Time As TIMECAPS
  TimeGetDevCaps( Time, SizeOf(Time) )
  TimeBeginPeriod(Time.wPeriodMin)
  'Sleep 16 ' Pre Windows 10 - high resolution does not 'byte' until next clock tick.
End Macro

Macro RevokeHiRes
  MacroTemp Time
  Dim Time As TIMECAPS
  TimeGetDevCaps( Time, SizeOf(Time) )
  TimeEndPeriod(Time.wPeriodMin)
End Macro

Global qFreq As Quad

Sub SleepX( ByVal n As Double )
  Local qTarget, qTimeNow As Quad
  QPC
  qTarget = qTimeNow + n*qFreq*0.001
  If n <= 3 then
    Do : QPC : Loop Until qTimeNow >= qTarget ' Class A amplifier analogy
  Else
    ' Class B amplifier analogy followed by Classs A amplifier analogy
    Sleep ( n-3 ) : Do : QPC : Loop Until qTimeNow >= qTarget
  End If
End Sub

' ====================

' EXAMPLE USAGE:

Function Pbmain () As Long
Local i as Long
Local qStart, qStop As Quad

  QueryPerformanceFrequency qFreq

  SetHiRes

  QueryPerformanceCounter qStart
    SleepX(0.25)
  QueryPerformanceCounter qStop
  Print "Quarter of a millisecond:";(qStop - qStart)*1000/qFreq;"ms"
  Print

  QueryPerformanceCounter qStart
    SleepX(2000)
  QueryPerformanceCounter qStop
  Print "2 seconds:";(qStop - qStart)/qFreq;"s"
  Print

  QueryPerformanceCounter qStart
    SleepX(1234)
  QueryPerformanceCounter qStop
  Print "Silly:";(qStop - qStart)*1000/qFreq;"ms"
  Print

  For i = 1 to 30
    QueryPerformanceCounter qStart
      SleepX(i)
    QueryPerformanceCounter qStop
    Print i;" ";(qStop - qStart)*1000/qFreq;"ms"
  Next

  RevokeHiRes

  WaitKey$

End Function

Print this item

  If you want to get to the PB Forum, do this
Posted by: Albert Richheimer - 01.09.2025, 05:53 PM - Forum: Suggestions and discussion about PUMP - No Replies

I have moved Carlo's thread into the members area, in Issues About The PowerBASIC Forum

Should be a better solution, so that the new PB owners won't be aware that we still have access to forum.powerbasic.com.

Print this item

  Clockwise sort of coordinates
Posted by: Torkel M. Jodalen - 30.08.2025, 10:33 AM - Forum: Programming - Replies (3)

Anyone who cares to post the final iteration of the "clockwise sort of coordinates" source code, which was recently discussed in the PB forums? I waited too long to store a local copy.

Thanks.

Print this item

  Pac-Man maze
Posted by: Jules Marchildon - 30.08.2025, 04:28 AM - Forum: Programming - Replies (11)

I'm starting to work on a pac-man maze.  I have a long road ahead of me with this challenge.   I'm going with a technique I read up on using tiles that are setup as a grid that allows you to draw the maze dynamically.  Each tile is stored in a 2D array.  The maze is setup 28 across and 31 tiles down.  The array elements are structures that allow you to include properties or attributes about the tile and can be used for game flow logic and drawing updates.   I'm curious to know if anyone else in PB land has done any work in this area?  TIA. 

A picture of what I have so far... (obviously more work to be done )
   

Print this item

  Hardware via USB
Posted by: Tillmann Viefhaus - 05.07.2025, 07:52 AM - Forum: Special Interest Groups - Replies (2)

How could I detect and handle for example a webcam with Power Basic?
I have no experience with this topic.

Print this item

  The FILECOPY command
Posted by: Tillmann Viefhaus - 15.06.2025, 06:04 PM - Forum: PowerBASIC for Windows - Replies (4)

When I write:

CHDR "D:\Test_with_Files"

A = "Original.exe"
B = "Original_Copy.exe"
Filecopy A, B

A is existing on the harddrive but File B is not created. Why is that?

Print this item

  Getting Current UTC
Posted by: Owen_English - 30.05.2025, 07:22 AM - Forum: PowerBASIC for Windows - Replies (14)

Have waded back thru the previous forum posts but at a loss to get an answer.
Sorry if it's been asked before but all I need is the numerical string for the Current UTC timestamp.
How?
Thanks.

Print this item

  PB 3.5 8-to-7 Bit Text Compression
Posted by: Andy Dee - 03.04.2025, 11:55 PM - Forum: Source Code Library - No Replies

Hello everyone, 
I developed a method to compress short texts by reducing 8-bit characters to 7-bit. While the compression ratio is low for large files, it efficiently reduces small strings. 

Key Steps

  1. Normalization: The input text is restricted to 7-bit ASCII (32–127).
  2. Offset Adjustment: Each character is decremented by 32 to fit within 0–95. 
  3. Compression
    For every 8 bytes, extract bits 0–6 (discarding bit 7).Pack these 7-bit segments into 7 bytes, using all 8 bits per byte. 
  4. Remaining Bytes: If the text length isn’t a multiple of 8, the last 1–7 bytes are copied uncompressed.
  5. Decompression
    Reverse the process: Expand 7-bit segments to 8 bits, then increment by 32. 

Here is the code, including some testing:

Code:
$Compile exe
$Dim All
$Lib All Off
$Error All Off
$String 2
$Com 0
$Float Procedure
$Optimize Size'Speed
$Cpu 80386
$Sound 1
$Stack 1536


'----------------------------------------------------------------------------
' Packe limitierten Text von 8 auf 7 Bit.
' Nutze dafür Zeiger zum Erhöhen der Geschwindigkeit
Declare _
FUNCTION PackTxt87 (sQuelle AS STRING) AS STRING
FUNCTION PackTxt87 (sQuelle AS STRING) AS STRING
  ' lokale Variablen
  DIM iQlen  AS LOCAL INTEGER          ' Länge von sQuelle
  DIM Q_ptr  AS LOCAL BYTE PTR         ' Zeichen-Pointer auf sQuelle
  Dim sZiel  As Local String           ' Komprimiertes sZiel
  DIM iZlen  AS LOCAL INTEGER          ' Länge von sZiel
  DIM Z_ptr  AS LOCAL BYTE PTR         ' Zeichen-Pointer auf sZiel
  DIM iZPos  AS LOCAL INTEGER          ' Position in sZiel
  DIM iQPos  AS LOCAL INTEGER          ' Position in sQuelle
  DIM iQLoop AS LOCAL INTEGER          ' Anzahl KompressionsSchleifen
  DIM iKompS AS LOCAL INTEGER          ' Anzahl komprimierbarer Zeichen
  Dim iRest  As Local Integer          ' Anzahl unkomprimierbarer Zeichen
  Dim bWert  As Local Byte             ' ASCII-32-Wert eines Zeichens.
  Dim iBitQ  As Local Integer          ' Aktuelle Bitbosition in sQuelle
  Dim iBitZ  As Local Integer          ' Aktuelle Bitbosition in sZiel
  Dim sTemp  As Local String

                                       '
  iQlen = LEN(sQuelle)                 ' Hole Länge der Quelle

  '--------------------------------------------------------------------------
  ' Fehler 1 abfangen
  If iQlen < 8 Then _                  ' String zu kurz?
    Function = sQuelle: _              ' Gib Original zurück
    Exit Function                      ' und raus

  iQLoop  = Fix(iQlen/8)               ' Hole Anzahl KompressionsSchleifen
  iRest  = iQlen Mod 8                 ' Hole Anzahl unkomprimierbarer Zeichen
  iKompS = iQLoop * 8                  ' Hole Anzahl komprimierbarer Zeichen
  iZlen  = iQLoop * 7 + iRest          ' Hole Länge komprimierten Strings
                                       '
  DECR iQlen                           ' Null-basiert für Pointer
  Q_ptr = STRPTR32( sQuelle )          ' Setze Pointer auf sQuelle

  '--------------------------------------------------------------------------
  ' Fehler 2 abfangen
  For iQPos = 0 To iQlen               ' Überprüfe auf ungültige Zeichen
    IF @Q_ptr[iQPos] < 32 _
      Or @Q_ptr[iQPos] > 159 _
      THEN
      sZiel = sZiel _                  ' sammle diese
            + Chr$(@Q_ptr[iQPos])
    End If
  Next iQPos

  If Len(sZiel) Then _
    Function = "Falsche Quelle: "+sZiel : _
    Exit Function                      ' und gib sie zurück

  sZiel = Repeat$(iZlen,Chr$(0))       ' Platz für Kompression in sZiel

  Z_ptr = STRPTR32( sZiel  )           ' Setze Pointer auf sZiel
  iZPos = 0                            ' Position im Pointer = 0
  iBitQ = 0                            ' Bitbosition in sQuelle auf 0
  iBitZ = 0                            ' Bitbosition in sZiel  auf 0

  DECR iKompS                          ' Null-basiert für Pointer

  '--------------------------------------------------------------------------
  ' Kompression:
  For iQPos = 0 To iKompS              ' Für komprimierbare Zeichen in sQuelle:
                                       ' 1. Schritt:
    bWert = @Q_ptr[iQPos] - 32         ' ASCII-Wert um 32 vermindern, dass
                                       ' ASCII zwischen 0-159 ist
    For iBitQ = 0 To 6                 ' Lies aus sQuelle Bit 0-6

      If Bit(bWert,iBitQ) = 1 Then     ' Schreibe Ziel-Bits 0-7
        Bit Set @Z_ptr[iZPos], iBitZ   '
      Else                             '
        Bit ReSet @Z_ptr[iZPos], iBitZ '
      End If

      If iBitZ < 7 Then                ' Solange in Ziel zwischen Bit 0 und 7
        Incr iBitZ                     ' Nächstes Bit
      Else                             ' sonst
        iBitZ = 0                      ' Bit 0 in
        Incr iZPos                     ' nächstem Zeichen
      End If
    Next iBitQ
  Next iQPos

  iZPos = iZlen-iRest                  ' Setze Zeiger auf erstes unpackbares
                                       ' Zeichen
  For iQPos = iQlen-iRest+1 To iQlen   ' Für unpackbare Zeichen in sQuelle
    @Z_ptr[iZPos] = @Q_ptr[iQPos]      ' Schreibe unpackbare Zeichen
    Incr iZPos
  Next iQPos


  Function = sZiel

END FUNCTION


'----------------------------------------------------------------------------
' EntPacke limitierten Text von 8 auf 7 Bit.
' Nutze dafür Zeiger zum Erhöhen der Geschwindigkeit
Declare _
FUNCTION DePackTxt87 (sQuelle AS STRING) AS STRING
FUNCTION DePackTxt87 (sQuelle AS STRING) AS STRING
  ' lokale Variablen
  DIM iQlen  AS LOCAL INTEGER          ' Länge von sQuelle
  DIM Q_ptr  AS LOCAL BYTE PTR         ' Zeichen-Pointer auf sQuelle
  Dim sZiel  As Local String           ' Komprimiertes sZiel
  DIM iZlen  AS LOCAL INTEGER          ' Länge von sZiel
  DIM Z_ptr  AS LOCAL BYTE PTR         ' Zeichen-Pointer auf sZiel
  DIM iZPos  AS LOCAL INTEGER          ' Position in sZiel
  DIM iQPos  AS LOCAL INTEGER          ' Position in sQuelle
  DIM iQLoop AS LOCAL INTEGER          ' Anzahl KompressionsSchleifen
  DIM iKompS AS LOCAL INTEGER          ' Anzahl komprimierbarer Zeichen
  Dim iRest  As Local Integer          ' Anzahl unkomprimierbarer Zeichen
  Dim bWert  As Local Byte             ' ASCII-32-Wert eines Zeichens.
  Dim iBitQ  As Local Integer          ' Aktuelle Bitbosition in sQuelle
  Dim iBitZ  As Local Integer          ' Aktuelle Bitbosition in sZiel
  Dim sTemp  As Local String
  Dim bPack  As Local Byte             ' Gepackte Bytes an sQuelleEnde

  iQlen = LEN(sQuelle)                 ' Hole Länge der Quelle

  '--------------------------------------------------------------------------
  ' Fehler 1 abfangen
  If iQlen < 7 Then _                  ' String zu kurz?
    Function = sQuelle: _              ' Gib Original zurück
    Exit Function                      ' und raus

  Q_ptr = STRPTR32( sQuelle )          ' Setze Pointer auf sQuelle

  iQLoop  = Fix(iQlen/7)               ' Hole Anzahl EntPacksSchleifen
  iRest  = iQlen Mod 7                 ' Anzahl ungepackte Zeichen?

  '--------------------------------------------------------------------------
  ' Fehler 2 abfangen

If iRest = 0 Then                      ' Scheint alles gepackt zu sein, dann
  bPack = 0                            ' GePacktes = 0
  For iQPos = iQlen - 7 To iQlen-1     ' Überprfe letzte 7 Zeichen auf
    IF @Q_ptr[iQPos] < 32 _            ' komprimierte Zeichen
      Or @Q_ptr[iQPos] > 127 _         ' Wenn welche da, dann
      THEN Incr bPack                  ' Erhöhe Gepacktes (bPack)
  Next iQPos
End If


  If bPack = 0? _                      ' Wenn keine gepackten Zeichen (bPack)
    And iRest = 0 _                    ' und keine ungepackten Zeichen (iRest)
    Then                               ' dann
    iRest = 7                          ' ungepackte Zeichen (iRest) = 7
    iKompS = iQlen - iRest             ' Setze Anzahl entpackbarer Zeichen
  Else                                 ' sonst
    iKompS = iQLoop * 7                ' Setze Anzahl entpackbarer Zeichen
  End If


  If IsFalse(bPack) _                  ' Sind die iRest-lichen Zeichen
    And iRest = 7 _                    ' ungepackt, dann reduziere
    Then Decr iQLoop                   ' die Anzahl der Entpackaufrufe


  iZlen  = iQLoop * 8 + iRest          ' Hole Länge komprimierten Strings
                                       '
  DECR iQlen                           ' Null-basiert für Pointer

  sZiel = Repeat$(iZlen,Chr$(0))       ' Platz für Kompression in sZiel

  Z_ptr = STRPTR32( sZiel  )           ' Setze Pointer auf sZiel
  iZPos = 0                            ' Position im Pointer = 0
  iBitQ = 0                            ' Bitbosition in sQuelle auf 0
  iBitZ = 0                            ' Bitbosition in sZiel  auf 0

  '--------------------------------------------------------------------------
  ' DeKompression: Rechne Zeichen in sQuelle auf ASCII 32-159 um
  For iQPos = 0 To iKompS              ' Fr entkomprimierbare Zeichen in sQuelle:
                                       ' 1. Schritt:
    For iBitQ = 0 To 7                 ' Lies aus sQuelle Bit 0-7

      If Bit(@Q_ptr[iQPos],iBitQ) = 1 Then ' Schreibe Ziel-Bits 0-7
        Bit Set @Z_ptr[iZPos], iBitZ   '
      Else                             '
        Bit ReSet @Z_ptr[iZPos], iBitZ '
      End If

      If iBitZ < 6 Then                ' Solange in Ziel zwischen Bit 0 und 6
        Incr iBitZ                     ' Nächstes Bit
      Else                             ' sonst
        iBitZ = 0                      ' Bit 0
        Incr @Z_ptr[iZPos], 32         ' Erstelle das richtige ZielZeichen
        Incr iZPos                     ' und nächstes ZielZeichen
      End If

    Next iBitQ

  Next iQPos

  iZPos = iZlen-iRest                  ' Setze Zeiger auf erstes unpackbares
                                       ' Zeichen
  For iQPos = iQlen-iRest+1 To iQlen   ' Für ungepackte Zeichen in sQuelle
    @Z_ptr[iZPos] = @Q_ptr[iQPos]      ' Schreibe ungepackte Zeichen
    Incr iZPos
  Next iQPos


  Function = sZiel

END FUNCTION


' Test-Code'

DIM originalText AS STRING, _
    compressedText AS STRING, _
    decompressedText AS STRING, _
    iIndex As Integer, _
    iLOrg  As Integer, _
    iLPck  As Integer, _
    iLEpk  As Integer

For iIndex = 07 To 19
  '?
  originalText = Left$("PowerBASIC 3.5 is a wonderful tool for writing fast and usefull programs.",iIndex)

  iLOrg = Len(originalText)
  compressedText = PackTxt87(originalText)
  iLPck = Len(compressedText)
  If Instr(compressedText, "Falsche Quelle: ") = 1 Then ?compressedText:end
  decompressedText = DePackTxt87(compressedText)
  iLEpk = Len(decompressedText)
  'PRINT "Original:      ";
  PRINT "Original: ";
  Print originalText;
  $If 0
  Print " ist =";iLOrg;" Byte lang"
  PRINT "Komprimiert:  ";
  Print compressedText;
  Print " ist =";iLPck;" Byte lang"
  PRINT "Dekomprimiert: ";
  Print decompressedText;
  Print " ist =";iLEpk;" Byte lang"
  $EndIf
  ? " --> Test verlief: [erfolg";
  If originalText = decompressedText Then
    Print "reich] :-)  :";iLOrg;iLPck;iLEpk
  Else
  Print "los] ;-(";iLOrg;iLPck;iLEpk
  ?"Original und wieder Entpacktes unterscheiden sich an folgenden Stellen:"
  For iIndex = 1 To iLOrg
    If ASCII(originalText,iIndex) <> ASCII(decompressedText,iIndex) Then
        ?"Position";iIndex;" - Zeichen Original: ";Chr$(ASCII(originalText,iIndex)); _
        " - Zeichen Entpackt: ";Chr$(ASCII(decompressedText,iIndex))
      End If
    Next iIndex
  End If

Next iIndex

Sleep

originalText = "PowerBASIC 3.5 is a wonderful tool for writing fast, small and usefull programs under DOS."
iLOrg = Len(originalText)
compressedText = PackTxt87(originalText)
iLPck = Len(compressedText)
If Instr(compressedText, "Falsche Quelle: ") = 1 Then ?compressedText:end
decompressedText = DePackTxt87(compressedText)
iLEpk = Len(decompressedText)
 
  PRINT "Original:"
  Print originalText;
  ? " --> Test verlief: [erfolg";
  If originalText = decompressedText Then
    Print "reich] :-)  :";iLOrg;iLPck;iLEpk
  Else
  Print "los] ;-(";iLOrg;iLPck;iLEpk
  ?"Original und wieder Entpacktes unterscheiden sich an folgenden Stellen:"
  For iIndex = 1 To iLOrg
    If ASCII(originalText,iIndex) <> ASCII(decompressedText,iIndex) Then
        ?"Position";iIndex;" - Zeichen Original: ";Chr$(ASCII(originalText,iIndex)); _
        " - Zeichen Entpackt: ";Chr$(ASCII(decompressedText,iIndex))
      End If
    Next iIndex
  End If
 
  PRINT "Komprimiert:"
  Print compressedText
  Print "ist =";iLPck;" Byte lang"
  PRINT "Dekomprimiert:"
  Print decompressedText
  Print "ist =";iLEpk;" Byte lang"



originalText = "PowerBASIC 3.5 ist ein wundervolles Werkzeug fr schnelle, kleine bis groáe und vor allen ¯ntzliche® Programme unter DOS."
?originalText
iLOrg = Len(originalText)
compressedText = PackTxt87(originalText)
iLPck = Len(compressedText)
If Instr(compressedText, "Falsche Quelle: ") = 1 Then ?compressedText:end
decompressedText = DePackTxt87(compressedText)
iLEpk = Len(decompressedText)
 
  PRINT "Original:"
  Print originalText;
  ? " --> Test verlief: [erfolg";
  If originalText = decompressedText Then
    Print "reich] :-)  :";iLOrg;iLPck;iLEpk
  Else
  Print "los] ;-(";iLOrg;iLPck;iLEpk
  ?"Original und wieder Entpacktes unterscheiden sich an folgenden Stellen:"
  For iIndex = 1 To iLOrg
    If ASCII(originalText,iIndex) <> ASCII(decompressedText,iIndex) Then
        ?"Position";iIndex;" - Zeichen Original: ";Chr$(ASCII(originalText,iIndex)); _
        " - Zeichen Entpackt: ";Chr$(ASCII(decompressedText,iIndex))
      End If
    Next iIndex
  End If
 
  PRINT "Komprimiert:"
  Print compressedText
  Print "ist =";iLPck;" Byte lang"
  PRINT "Dekomprimiert:"
  Print decompressedText
  Print "ist =";iLEpk;" Byte lang"


This is the DOS-output:
Code:
Original: PowerBA --> Test verlief: [erfolgreich] :-)  : 7  7  7
Original: PowerBAS --> Test verlief: [erfolgreich] :-)  : 8  7  8
Original: PowerBASI --> Test verlief: [erfolgreich] :-)  : 9  8  9
Original: PowerBASIC --> Test verlief: [erfolgreich] :-)  : 10  9  10
Original: PowerBASIC  --> Test verlief: [erfolgreich] :-)  : 11  10  11
Original: PowerBASIC 3 --> Test verlief: [erfolgreich] :-)  : 12  11  12
Original: PowerBASIC 3. --> Test verlief: [erfolgreich] :-)  : 13  12  13
Original: PowerBASIC 3.5 --> Test verlief: [erfolgreich] :-)  : 14  13  14
Original: PowerBASIC 3.5  --> Test verlief: [erfolgreich] :-)  : 15  14  15
Original: PowerBASIC 3.5 i --> Test verlief: [erfolgreich] :-)  : 16  14  16
Original: PowerBASIC 3.5 is --> Test verlief: [erfolgreich] :-)  : 17  15  17
Original: PowerBASIC 3.5 is  --> Test verlief: [erfolgreich] :-)  : 18  16  18
Original: PowerBASIC 3.5 is a --> Test verlief: [erfolgreich] :-)  : 19  17  19

Original:PowerBASIC 3.5 is a wonderful tool for writing fast, small and usefull
programs under DOS. --> Test verlief: [erfolgreich] :-)  : 90  79  90
Komprimiert:
░τ╡(§àf⌐◄`Γ¿ ÆS@►p}:ëE⌐▒╩♦PƒO&└°ö☻«╥$5Θ<☻î┴)ò☺ÿ6âL& Φ$☻¬╙ó▒╩d☻á╥τQ→lN☺U'▒(♣É^S.
ist = 79  Byte lang
Dekomprimiert:
PowerBASIC 3.5 is a wonderful tool for writing fast, small and usefull programs
under DOS.
ist = 90  Byte lang
PowerBASIC 3.5 ist ein wundervolles Werkzeug für schnelle, kleine bis große und
vor allen »nützliche« Programme unter DOS.
Falsche Quelle: ß»« 

Perhaps the code will also be of use to others...

Print this item

  $EOF when using Line Input#
Posted by: Albert Richheimer - 12.03.2025, 09:25 AM - Forum: PowerBASIC Console Compiler - No Replies

Source code moved from PB DOS over here, in reply to @Andy Dee:

Code:
#compile exe
#dim all

function pbmain () as long
    local hFile as long
    local sFile as string
    local sTemp as string

    '
    ' Setup strings
    ' -------------
    '
    sTemp = "ABCDEF" + $EOF + "abcdef"
    sFile = "Data.txt"

    '
    ' Create Data.txt
    ' ---------------
    '
    hFile = freefile
    open sFile for output as #hFile
    print #hFile,sTemp;
    close #hFile

    '
    ' Read Data.txt using get$
    ' ------------------------
    '
    hFile = freefile
    open sFile for binary as #hFile
    get$ #hFile,lof(hFile),sTemp
    close #hFile
    stdout "Using get$:        "+sTemp

    '
    ' Read Data.txt using line input#
    ' -------------------------------
    '
    hFile = freefile
    open sFile for input as #hFile
    line input #hFile,sTemp
    close #hFile
    stdout "Using line input#: "+sTemp

    '
    ' Clean up
    ' --------
    '
    kill sFile

end function

Print this item

  Leap days (or not) in February for PBDOS
Posted by: Dale Yarker - 08.03.2025, 09:48 AM - Forum: Source Code Library - Replies (2)

'DECLARE not needed if FUNCTION source is before the CALL
'here the CALL is in PBMAIN
'I call it bottom up because PBMAIN is last and flow goes up
'
'Pretty sure PUSHes and POPs not needed in FUNCTION
'They will be needed to use "inside" code in-line with BASIC
'
'Used PBCC v6 to test. I no longer have PBDOS available.
function Tage_im_Februar(byval iJahr as integer) as integer
  local FebruarTage as integer
  ! push ax
  ! mov FebruarTage, 28&  'not a leap year, pre-set to 28
  ! mov ax, 1582%
  ! cmp ax, iJahr
  ! jge Julian
  ! mov ax, 3%
  ! and ax, iJahr    'conditionally equivalent MOD 4
  ! jz MOD100        '0 is possible leap year
  ! jmp Done
  MOD100:
  ! push bx          'for divisor
  ! push dx          'for high part of dividend, remainder (MOD)
  ! xor dx, dx
  ! mov ax, iJahr
  ! mov bx, 100%
  ! div bx
  ! cmp dx, 0%    'does MOD 100 = 0 ?
  ! pop dx
  ! pop bx
  ! jz MOD400        '0 is possibly not a leap year
  ! jmp Is29Days      'non 0 is a leap year
  MOD400:
  ! and ax, 3%    'EAX has Year\100, so conditionally equivalent MOD 400
  ! jnz Done
  Julian:
  ! mov ax, 3%
  ! and ax, iJahr
  ! jnz Done
  Is29Days:
  ! mov FebruarTage, 29%
  Done:
  ! pop ax
  function = FebruarTage
end function
function pbmain () as long 'put only to demonstrate Tage_im_Februar
  local iJahr as integer
  iJahr = 2000
  print Tage_im_Februar(iJahr); " 2000, divisible by 400, is leap"
  iJahr = 2100
  print Tage_im_Februar(iJahr); " 2100, divisible by 100 not 400, not leap"
  iJahr = 2104
  print Tage_im_Februar(iJahr); " 2104, divisible by 4 not 100, is leap"
  iJahr = 2103
  print Tage_im_Februar(iJahr); " 2103, not divide 4, not leap
  print "julian, did not check rule for prior to Gregorian myself"
  iJahr = 1204
  print Tage_im_Februar(iJahr); " 1204, divisible by 4, is leap
  iJahr = 1201
  print Tage_im_Februar(iJahr)  " 1201, not divisible by 4, not leap
  waitkey$
end function

Print this item