Announcement

Collapse
No announcement yet.

How effectively can a PBDOS program and a PBCC program communicate with each other?

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

  • How effectively can a PBDOS program and a PBCC program communicate with each other?

    Two .EXEs compiled in PBCC can communicate with each just great -- up to 1000 times per second, on my machine, in the case of SHARECC.BAS, as listed below.

    But how about an .EXE compiled in PBDOS and an .EXE compiled in PBCC? As of Windows XP, and certainly for SHAREDOS.BAS as listed below, the answer is "not so hot". That's where I need your help.

    Please correct the "Verbose Remarks" and the source code wherever you can; I will greatly appreciate it. And be sure to read the former if nothing seems to happen when you run one program or both in succession.

    Code:
    'Verbose Remarks
    'for ShareCC.BAS  and ShareDOS.BAS
    'by E.W. Menzel, Jr. (Emil Menzel)
    'July 2009
    'Freeware, placed in the Public Domain 
    'when posted to PB Forums, August 02, 2009
    'The basic program structure used here for sharing was posted by John Gleason, in:
    'http://powerbasic.com/support/pbforums/showthread.php?t=40334
    'I revised his program a bit for my own purposes.
    
    'Purpose:
    'At a relatively general level of discussion, study "inter process communication"
    'see e.g., http://en.wikipedia.org/wiki/Inter-process_communication
    ' and "exchange or sharing of data between two programs" [or operating systems,
    'or computers].
    
    'At a relatively concrete level of discussion,
    'Using as an example a game controller program, which demands high performance to be of much use,
    '1. Verify high performance sharing of info between 2 .EXE programs, both compiled in PBCC
    '2. Demonstrate the obvious relative "failures to communicate" (under Windows XP) if
    '   one of the .EXEs is compiled in PBDOS rather than PBCC.
    '3. Attempt to get the most speedy communication possible between a DOS .EXE &
    '   a WIN .EXE. But that is a job on which I need advice from the PB gurus.
    'Depending on how well we do on #3, we should be able to exploit PCCC (from PBDOS)
    'to do many things we could not do otherwise.
    'P.S. Before you say that a DOS program and a Windows program cannot share information at the
    'speed required for the present program, think again. There are already such Windows programs
    'that do the job just fine on my PBDOS programs --
    'e.g., the shareware program "Total game controller"
    'So if they can do it, why not PB programmers?
    
    'Instructions:
    'In Windows XP (or NT or higher),
    '1. Compile ShareCC.BAS IN PBCC
    '2. Make an additional copy of the .EXE, e.g., naming it ShareCC2.EXE
    '  (Alternatively, you could simply run ShareCC.EXE twice, in step 4.)
    '3. Press Ctrl-Alt-Del to call up Windows Task Manager.
    '   In Windows Task Manager, click Processes/CPU, then CPU once more
    '   Watch which processes will use the most CPU in step 4
    '4.  Start up one .EXE, then the other .EXE
    'The first program should do nothing until the second one is started.
    'After #2 starts, both programs should finish very shortly. Obviously, they are sharing data.
    'If you use SLEEP 0, or no SLEEP statement, just before the ITERATE DO statement,
    'the programs will use up to 100% of the CPU. SLEEP 10 drops that figure (and overall
    'speed) drastically.
    
    '5. Now make a copy of ShareCC.BAS, naming it (e.g.) ShareDOS.BAS
    'Revise it to your own needs
    'Compile it in PBDOS. Some changes will be necessary --
    'Cf SUB Sleeper vs SLEEP. BASE 0 rather than 1 for SEEK. See also the Footnote, below.
    'A sample ShareDOS.BAS is provided
    
    'After compiling, run first SHARECC.EXE & then SHAREDOS.EXE
    'Wait -- it might be several minutes before anything happens
    '(If file c:\shar.DTA exists & is 70 bytes long & contains the words "HiHAL.Wav", something has happened)
    'The action will be much faster if you get the Windows Focus back on SHARECC.EXE
    
    ' When 2 PBDOS .EXE's are run, or when 1 PBDOS & 1 PBCC .EXE are run,
    ' sharing can still occur, but it will be at a much slower pace (in Windows XP).
    ' CPU usage jumps up to almost 100%, and can be hogged almost entirely by Microsoft
    ' ntvdm.exe, i.e., Virtual DOS for Windows NT & higher. It seems safe to stop ntvdm.exe from
    ' the Windows Manager. (It will reappear the next time you run a DOS program.) But stopping
    ' it will also stop your running DOS program(s). To be more precise, you will not see the
    ' names of the PBDOS .EXEs at all; they are subsumed under ntvdm.exe. If you use 2 PBDOS
    ' .EXEs you will see 2 copies of ntvdm.exe, and they will split the CPU between themselves.
    
    'What is ntvdm, & what does it do? Here is a quote from http://sourceforge.net
    '"Although Windows*NT (and its successors Windows*2000 and XP) is able to run DOS
    'programmes within a Virtual DOS Machine (NTVDM), this environment is very limited:
    'There's no access to most software and hardware that's available under a normal DOS
    'environment or even within a DOS box on Windows*95/98/Me.
    'The NTVDM does, however, allow to emulate nearly all DOS APIs and hardware through
    'so-called Virtual Device Drivers (VDDs). Here you will find a list of available VDDs
    'created here as well as links to drivers created by others."
    'The list of available VDDs includes ones for joysticks, sound cards, clipboard access,
    'COM port control, long file name support, and (incoming) TelNet connections.
    
    'Important Footnote, especially if security can be an issue in your use of the programs:
    '(A comment by Michael Mattias on John Gleason's code)
    'That code does not prevent simultaneous access... you never lock the disk file record.
    'Here is an article I wrote a long time ago about using files to share data across
    'processes. The code is PB/DOS, but it's not really the code which is important, it's
    'the concepts.
    ' "Fundamentals Of Multi-User Programming."
    ' Article published in December 1995 issue of "BASICally Speaking" magazine
    ' discussing the principles of writing multi-user programs; code samples in [DOS]BASIC.
    'http://www.talsystems.com/tsihome_ht...rogramming.rtf

    Code:
    'SHARECC.BAS
    'Freeware, Public Domain, by Emil Menzel
    'Compile in PBCC (I developed in in ver 5.01)
    $BREAK ON        'REM-out for PBDOS
    $COMPILE EXE
    $DIM ALL
    $INCLUDE ONCE "Win32api.INC"
    
    TYPE JoyInfoType
            Time AS LONG   'Windows time, in millisec
    
            'Joystick: X,Y,Z readings range from 0 to 65536; center=32767
            'Calibrate your joystick with Windows Start/ControlPanel/Game Controllers
            JX AS LONG        'joystick X axis
            JY AS LONG        'joystick Y
            JZ AS LONG        'joystick Z. will read 0 if your joystick is not 3-D
            JB AS LONG        'joystick button(s) status
    
            'Mouse readings from Win32 api can range from 0 to max resolution of your Display,
            'as set by Windows Start/ControlPanel/Display/Settings
            MX AS LONG        'Mouse X, on screen as a whole, according to Windows
            MY AS LONG        'Mouse Y, on screen as a whole, according to Windows
            MB AS LONG        'Mouse button(s) status
    
            'Keyboard: Status according to win api function GetKeyState
            'This does not include Shift state, etc.
            ' ("Needs improvement", most teachers would say)
            KyBd AS LONG
            'Add keyboard shift status, etc here if you wish
            'Add serial port,
            'and old gameport status here too, as you wish
    
            ID AS SINGLE          'identify which program read or wrote to the .DTA last
    
            'Error Messages, &/or commands from the PBDOS program, to be executed by
            'the PBCC program.
            Message AS STRING * 30  'use fixed strings for all messages, to keep
                                    'the .DTA file lines exactly equal in length
    
    END TYPE
    
    DECLARE SUB Sleeper(timeinsec AS SINGLE)  'for PBDOS
    DECLARE SUB Play(SynAsync AS INTEGER, WavFileName AS STRING) 'for PBCC/PBWIN
    DECLARE FUNCTION KeyStat() AS LONG        'for PBCC/PBWIN
    DECLARE FUNCTION PBMAIN() AS LONG
    
    '''PRINT PBMAIN                           'un-REM for PBDOS
    
    FUNCTION PBMAIN () AS LONG
        DIM Jinfo AS JoyInfoType     'room for identifier and all member elements
        DIM JS AS JOYINFO   'JoyInfo is defined in win api --x,y,z status of joystick + buttons code
                            'At least in PBCC, JS can also be treated as a string
                            '4 bytes for each of the various LONG integers
                            'This info can be passed to other subroutines in a single 16 byte string,
    
        DIM pt AS PointAPi  ' as defined in win api -- x,y of (e.g.) Mouse
    
        DIM ii AS LONG
        DIM StickError AS LONG
        DIM Count0 AS QUAD
        DIM Count1 AS QUAD
        DIM t AS SINGLE
        DIM identifier AS SINGLE
        DIM ky AS STRING
        DIM A AS STRING
        DIM DataFileName AS STRING
    
    
        RANDOMIZE TIMER
        t=TIMER     'use TIX to get quad identifier guaranteed unique.
                    '(TIMER usually okay too unless exe's run < 18/th sec. apart)
        DO: LOOP UNTIL TIMER > t
        t=TIMER
        identifier = t                              'give this exe the unique identifier
        DataFileName ="c:\shar.dta"                 'Warning: SHAREDOS.EXE can't read long file names
        KILL DataFileName                           'clear previous test runs
    
        Jinfo.ID = identifier                    'put unique identifier in the data
        OPEN DataFileName FOR BINARY LOCK SHARED AS #1 'be sure to make SHARED
        PUT #1,, Jinfo                           'initialize. write opening string
    
    
      DO UNTIL ky$ = CHR$(27) OR INSTR(Jinfo.Message,"QUIT")= 1
      '--------Here is the actual sharing code----------------------------------------------
        DO UNTIL INSTAT      'The INSTAT check is for debug only.
                             'I.e., press any key to read the current Counts
           SEEK #1, 1                            'seek to beginning
           GET #1,, Jinfo                        'read in whole UDT
           IF Jinfo.ID = identifier THEN         'if it's from this exe, it's not our turn yet, so iterate after short sleep
              SLEEP 10      'For PBDOS program(s) CALL Sleeper(timeInSec) instead
                             'Adjust SLEEP time for optimal performance (for your own purposes)
                             'SLEEP 0 is fine ... to test max speed, anyway
              INCR Count0    'use for debugging or test only
              ITERATE DO
           ELSE
              INCR Count1  'use for debug or test only
              GOSUB ProcessInfo
           '''Jinfo.ID = identifier              'I moved this line into the GOSUB
              SEEK #1, 1                            'seek to beginning
              PUT #1,, Jinfo                        'and write it
              EXIT DO
           END IF
        LOOP
      '---------End of the actual sharing code----------------------------------------------
        ky$ = INKEY$
        GOSUB ShowInfo
        'make a click... A good way (in debugging) to tell how fast the program is running
        'try both SyncAsync=0 & =1
        '''CAll Play (1, "SOUND111.WAV")   'see Windows WAV file collection
      LOOP
    
      CLOSE #1
      IF DIR$(DataFileName)<>"" THEN KILL DataFileName 'delete data file
      PRINT "Done in" & STR$(ROUND(TIMER - t, 3)) & " sec"
      PRINT "Press any key"
    
      WAITKEY$        'for PBDOS use ky$ = INPUT$(1)
      EXIT FUNCTION
    
      '===== GOSUBs ================================
       ProcessInfo:
            'First read the Message from the other program & act on it
            'add your own code here
            '& post appropriate Messages for the other program
            'Get PBCC to do what PBDOS can't do, or can't do as well.
            'See, for starters, the list given on http://sourceforge.net
            'in its discussion of ntvdm.exe. Running DLLs & SHELLing without using
            'DOS cmd.exe would be also be relatively easy pieces.
    
            'Next,
            A$ = UCASE$(TRIM$(Jinfo.Message))
            IF INSTR(A$, ".WAV") THEN CALL Play(0,A$)
            Jinfo.Message = "ok"  'clear out old messages. New ones could be posted too
    
            'Get the current status of Windows keybord, clock,joystick & mouse with win api's
            Jinfo.KyBd = KeyStat                      'check keyboard & mouse buttons
                                                      'Note: this is regardless of which window has the focus now
            Jinfo.Time = GetTickCount                 'win api current time
            StickError = joyGetPos(0,JS)      'win api...reads stick#0
            IF StickError THEN Jinfo.Message = "StickError# "+STR$(StickError)
    
            Jinfo.JX = JS.wXpos
            Jinfo.JY = JS.wYpos
            Jinfo.JZ = JS.wZpos
            Jinfo.JB = JS.wButtons
            GetCursorPos Pt                           'win api mouse pos
            Jinfo.Mx = Pt.x
            Jinfo.My = Pt.y
    
            'better yet, get MouseButton status from Win32 api functions forbuttons, instead of this way
            Jinfo.MB = Jinfo.KyBd
            IF Jinfo.MB > 2 THEN Jinfo.MB = 0    'assuming max of 2 buttons
    
            '''ScreenToClient hWin, pt        'win api mouse pos on whichever window has the focus
                                              'could add this info too
            IF Jinfo.KyBd THEN
                ky$ = INKEY$           'keypress, if CONSOLE of this program has Windows focus
                IF ky$=CHR$(27) THEN Jinfo.Message = "QUIT"
                'or add your own code for handling this
                'ignore (at least here) keypresses on any other windows
            END IF
            'IMPORTANT! if you don't call this GOSUB, put the next line in the main loop, where John Gleason had it
            Jinfo.ID = identifier    'otherwise, our turn to write so set ID to our identifier
    
       RETURN
    
       ShowInfo:
          LOCATE 10,1
          PRINT "Time "+STR$(Jinfo.Time)+SPACE$(5)
          PRINT " JX  "+ STR$(Jinfo.JX)+SPACE$(5)
          PRINT " JY  "+STR$(Jinfo.JY)+SPACE$(5)
          PRINT " JZ  "+STR$(Jinfo.JZ)+SPACE$(5)
          PRINT " JB  "+STR$(Jinfo.JB)+SPACE$(5)
          PRINT " MX  "+STR$(Jinfo.MX)+SPACE$(5)
          PRINT " MY  "+STR$(Jinfo.MY)+SPACE$(5)
          PRINT " MB  "+STR$(Jinfo.MB)+SPACE$(5)
          PRINT "KyBd "+STR$(Jinfo.Kybd)+SPACE$(5)
          PRINT " ID  "+STR$(Jinfo.ID)
          PRINT " Msg "+Jinfo.Message+"|"
    
          LOCATE 23, 1
          A$="Count0"+STR$(Count0)+ " Count1" + STR$(Count1)+ "  ID# "+ STR$(identifier)
          PRINT A$
       RETURN
    END FUNCTION
    
    $IF 0
    'use for PBDOS programs only
    SUB Sleeper (SleepTime AS SINGLE)
       'release a time slice
       'ASM code from PB Support
       DIM t AS SINGLE
       DIM iswindows AS INTEGER
    
       iswindows% = ISTRUE BIT(pbvhost,8)
       IF UCASE$(ENVIRON$("os")) = "WINDOWS_NT" THEN iswindows% = -1
    
       t=TIMER + SleepTime
       DO
          IF iswindows% THEN
             ! push ds
             ! mov ax, &h1680
             ! int &h2f
             ! pop ds
          END IF
       LOOP UNTIL TIMER > t
    END SUB
    
    $ENDIF
    
    'PB INKEY$ does not work on a graphics window.
    'KeyStat does -- albeit the returned keycodes are not all the same as INKEY$
    'It "needs work", PB gurus and indows gurus will say
    'But I leave it here as I posted it in 2005 in a thread called "NagBox"
    'Use in PBCC/PBWIN only; REM-out or delete for PBDOS
    FUNCTION keyStat() AS LONG
        LOCAL I,ks AS LONG
        DIM kb(255) AS STATIC BYTE
        GetKeyBoardState kb(0)   'win api
        FOR I=0 TO 255           'or .. ASC("A") to ASC("Z")
            ks=GetKeyState(I)    'win api
            IF ks<0 THEN EXIT FOR
        NEXT
        '''SLEEP 50          'watch out! fast-repeating keys
        IF I>255 THEN I=0
        FUNCTION=I
    END FUNCTION
    
    'Play a .WAV file (for PBCC/PBWIN only)
    'from a post by Mike Doty, on PB Forums, June 2009
    SUB Play(syncOrAsync AS INTEGER, sFileName AS STRING) EXPORT
      LOCAL zFileName AS ASCIIZ * 128
      IF LEN(sFileName) = 0 THEN sFileName = "tada"
      zFileName = sFileName + $NUL
      IF SyncOrAsync <>0 THEN SyncOrAsync = 1
      CALL PlaySound(zFileName, 0% , syncOrAsync)   ' sync=0=play sound until done
                                                    'async=1=start sound but don't wait
    END SUB

    Code:
    'ShareDOS.BAS  
    '(this requires also ShareCC.BAS. See Verbose Remarks)
    'Compile in PBDOS (I developed it in ver. 3.5)
    'by E.W. Menzel, Jr., a.k.a. Emil Menzel
    'July 2009
    'Freeware, placed in the Public domain
    'when posted to PB Forums August 2, 2009
    
    $COMPILE EXE
    $DIM ALL
    
    TYPE JoyInfoType
            Time AS LONG   'Windows time, in millisec
    
            'Joystick: X,Y,Z readings range from 0 to 65536; center=32767
            'Calibrate your joystick with Windows Start/ControlPanel/Game Controllers
            JX AS LONG        'joystick X axis
            JY AS LONG        'joystick Y
            JZ AS LONG        'joystick Z. will read 0 if your joystick is not 3-D
            JB AS LONG        'joystick button(s) status
    
            'Mouse readings from Win32 api can range from 0 to max resolution of your Display,
            'as set by Windows Start/ControlPanel/Display/Settings
            MX AS LONG        'Mouse X, on screen as a whole, according to Windows
            MY AS LONG        'Mouse Y, on screen as a whole, according to Windows
            MB AS LONG        'Mouse button(s) status
    
            'Keyboard: Status according to win api function GetKeyState
            'This does not include Shift state, etc.
            ' ("Needs improvement", most teachers would say)
            KyBd AS LONG
            'Add keyboard shift status, etc here if you wish
            'Add serial port,
            'and old gameport status here too, as you wish
    
            ID AS SINGLE          'identify which program read or wrote to the .DTA last
    
            'Error Messages, &/or commands from the PBDOS program, to be executed by
            'the PBCC program.
            Message AS STRING * 30  'use fixed strings for all messages, to keep
                                    'the .DTA file lines exactly equal in length
    
    END TYPE
    
    DECLARE SUB Sleeper(timeinsec AS SINGLE)  'for PBDOS. release time slice
    DECLARE FUNCTION PBMAIN() AS STRING
    
    PRINT PBMAIN                           'REM-out for PBCC
    
    FUNCTION PBMAIN () AS STRING
    
        DIM Jinfo AS JoyInfoType          'room for identifier and all member elements
        DIM ii AS LONG
        DIM LJI AS LONG
        DIM Count0 AS QUAD
        DIM Count1 AS QUAD
        DIM t AS SINGLE
        DIM identifier AS SINGLE
        DIM ky AS STRING
        DIM A AS STRING
        DIM Dt AS STRING
        DIM Msg AS STRING
        DIM DataFileName AS STRING
    
    
        RANDOMIZE TIMER
        t=TIMER     'use TIX to get quad identifier guaranteed unique (PBCC/PBWIN)
                    '(TIMER usually okay too unless exe's run < 18/th sec. apart)
        DO: LOOP UNTIL TIMER > t
        t=TIMER
        identifier = t                              'give this exe the unique identifier
        DataFileName ="c:\shar.dta"     'Same name as in SHARECC.BAS. Do NOT use long file names
    
        IF DIR$(DataFileName) = "" THEN
            PRINT "Run SHARECC.EXE before you run this program"
            GOTO AllDone
        END IF
    
    
        Jinfo.ID = identifier                    'put unique identifier in the data
        Jinfo.Message = "HiHal.WAV"              '.WAV is a keyword in SHARECC.exe
                                    'HiHal.WAV is my favorite startup sound for Windows
                                    'It is the voice of Hal, the computer in the movie "2001"
                                    'saying: Good evening, Dave. everything's going smoothly...
                                    'and you?...just a moment...just a moment.
        OPEN DataFileName FOR BINARY LOCK SHARED AS #1 'be sure to make SHARED
        SEEK #1,0                                'SHARECC.BAS uses BASE 1, not 0
        PUT #1,, Jinfo                           'initialize. write opening string
        LJI = LEN(Jinfo)
    
      DO UNTIL ky$ = CHR$(27)
      '--------Here is the actual sharing code----------------------------------------------
        DO UNTIL INSTAT      'The INSTAT check is for debug only.
                             'I.e., you can press any key to read the current Counts
           SEEK #1, 0        'seek to beginning... NOTE! SHARECC.BAS uses BASE 1, not 0
           GET #1,, Jinfo    'read in whole UDT
           Msg = UCASE$(TRIM$(Jinfo.Message))
           IF INSTR(Msg,"ERROR") THEN
              'use your own error handler code here; e.g.:
              'LOCATE 24,1: PRINT: PRINT Msg: GOTO AllDone
           ELSEIF Msg = "OK" OR Jinfo.ID <> identifier THEN   'assume "OK" is a Message from SHARECC.EXE
              INCR Count1  'this count is used for debug or test only
              GOSUB ProcessInfo              'do Dt$ string parsing, etc.
              Jinfo.ID = identifier            'otherwise, our turn to write so set e0 member to our identifier
              Jinfo.Message = "SOUND111.WAV"   '.WAV is a keyword for SHARECC.EXE to play a file
              SEEK #1, 0                       'seek to beginning...NOTE! ShareCC uses 1, not 0
              PUT #1,, Jinfo                        'and write it
              GOSUB ShowInfo
              CALL Sleeper (.05)                  'release a time slice (sec)
              EXIT DO
           ELSE                    'if it's from this exe, it's not our turn yet, so iterate after short sleep
              CALL Sleeper(.05)     'release a time slice.
              INCR Count0  'used for debugging or test only
              ITERATE DO
           END IF
        LOOP
      '---------End of the actual sharing code----------------------------------------------
        ky$ = INKEY$
      LOOP
    
      AllDone:
      CLOSE #1
      IF DIR$(DataFileName)<>"" THEN KILL DataFileName 'delete data file
      PRINT "Done in" & STR$(ROUND(TIMER - t, 3)) & " sec"
      PRINT "Press any key"
    
      ky$ = INPUT$(1)
      FUNCTION = ""
      EXIT FUNCTION
    
      '===== GOSUBs ================================
       ProcessInfo:
          'add your own code here
          '& post appropriate Messages for the other program
          'Get PBCC to do what PBDOS can't do, or can't do as
          'well. See, for starters, the list given on http://sourceforge.net,
          'in its discussion of ntvdm.exe.
          'Running DLLs & SHELLing without using
          'DOS cmd.exe are also relatively easy pieces.
    
       RETURN
    
       ShowInfo:
          LOCATE 10,1
          PRINT "Time "+STR$(Jinfo.Time)+SPACE$(5)
          PRINT " JX  "+ STR$(Jinfo.JX)+SPACE$(5)
          PRINT " JY  "+STR$(Jinfo.JY)+SPACE$(5)
          PRINT " JZ  "+STR$(Jinfo.JZ)+SPACE$(5)
          PRINT " JB  "+STR$(Jinfo.JB)+SPACE$(5)
          PRINT " MX  "+STR$(Jinfo.MX)+SPACE$(5)
          PRINT " MY  "+STR$(Jinfo.MY)+SPACE$(5)
          PRINT " MB  "+STR$(Jinfo.MB)+SPACE$(5)
          PRINT "KyBd "+STR$(Jinfo.Kybd)+SPACE$(5)
          PRINT " ID  "+STR$(Jinfo.ID)
          PRINT " Msg "+Jinfo.Message+"|"
    
          LOCATE 23, 1
          A$="Count0"+STR$(Count0)+ " Count1" + STR$(Count1)+ "  ID# "+ STR$(identifier)
          PRINT A$
      RETURN
    END FUNCTION
    
    'use for PBDOS programs only
    SUB Sleeper (SleepTime AS SINGLE)
       'release a time slice
       'ASM code is from PB Support
       DIM t AS SINGLE
       DIM iswindows AS INTEGER
    
       iswindows% = ISTRUE BIT(pbvhost,8)
       IF UCASE$(ENVIRON$("os")) = "WINDOWS_NT" THEN iswindows% = -1
    
       t=TIMER + SleepTime
       DO
          IF iswindows% THEN
             ASM push ds
             ASM mov ax, &h1680
             ASM int &h2f
             ASM pop ds
          END IF
       LOOP UNTIL TIMER > t
    END SUB
    Last edited by Emil Menzel; 5 Aug 2009, 08:48 PM.

  • #2
    After your PUT statements try using a FLUSH statement. It may not be flushing the file buffers right away.
    Scott Slater
    Summit Computer Networks, Inc.
    www.summitcn.com

    Comment


    • #3
      Also...

      replace

      Code:
      PRINT PBMAIN                           'REM-out for PBCC
      with...

      Code:
      END PBMAIN
      placed at the end of the file. It does what the windows compilers do then. It returns the result code to the OS (if one is set).

      You can also enclose it in a $IF / $ENDIF block something like...

      Code:
      %IS_PB_DOS = 1  ' Change to 0 for CCWin
      ...
      ...
      Function PBMain() AS LONG
      ...
      End Function
      ...
      ...
      $IF %IS_PB_DOS=1
      End PBMain
      $ENDIF
      Scott Slater
      Summit Computer Networks, Inc.
      www.summitcn.com

      Comment


      • #4
        On testing the programs further I found that they would not run correctly unless a joystick was connected. Sorry about that. Will correct for it if possible. Also there is an error in the verbose remarks: if you run 2 PBCC programs simultaneously, they do not stop after N message swaps. They keep going until you stop them.

        Earlier drafts of the programs started up quickly, so I'm not greatly worried about that bottle neck, and I'll certainly check out Scott's suggestion about FLUSH, to see what it does.

        The worst bottle necks are elsewhere. Whereas 2 PBCC programs can swap messages up to 1000 times per sec, as soon as a PBDOS program enters the picture, the rate can drop to less than 1 message exchange per sec. At least that is true right now, on my 2 machines, especially if the PBDOS program has Windows's focus. I suspect that the problem lies not entirely in the programs and in NTVDM.EXE but also in my current settings for other drivers or programs. As yet, however, I'm still mostly in the dark there.

        I have, coincidentally, run across a number of references on these forums to sharing information between PBDOS & PBCC/PBWIN programs, but I have never seen any accompanying source code. If anyone can point me to some sample source code, I'd appreciate it.

        A relevant question is, how many message swaps per sec would be acceptable? For some problems, even 1 might do. For a game controller program, 10 might do, but 20 or more would be better. And I am still hoping that the latter number is feasible.


        Scott:
        Thank you for your comments.

        Comment


        • #5
          You might also want to hunt around to look for some TCP functions for the DOS end of things. I'm pretty sure there was code around here for IPX communications and NetBIOS stuff for DOS, but don't recall any for TCP/IP. I'm sure you could find something on the net for PB or QB and translate it. You could then use the "localhost" as a way to establish communications between the two. I would of course make the Windows ap the server since you can run it in a thread and let it do its thing in the background.

          This approach would give you faster communications over the shared file approach.

          ** Another thing, maybe set up a virtual disk in windows and use it for the shared file access. In this case you would essentially be sharing memory.
          Scott Slater
          Summit Computer Networks, Inc.
          www.summitcn.com

          Comment


          • #6
            Scott:
            Thanks again.

            The old Ethan Winer Quickpack routines can do a flush-buffer in DOS BASIC, but I'm still searching for a freebie alternative. I suspect that PBDOS needs flushing more than PBCC does.

            I've been tempted to try the clipboard rather than a disk file for a place to post messages (in which case one could communicate between DOS, Windows, & Mac OS X on a MacBook Pro, if one were so inclined) but the virtual disk might be neater, & I'll have to try that too.

            Will get back to you on these & the other matters after I've done my homework.

            Comment


            • #7
              Flush is a built-in PB Command (statement) in both DOS and CC.

              Flush {file handle number}
              Scott Slater
              Summit Computer Networks, Inc.
              www.summitcn.com

              Comment


              • #8
                Thanks to Petr Schreiber, here's a translation of ShareCC.BAS into PBWin.
                Not surprisingly, the compiled versions of these two programs will communicate with each other very effectively.
                ShareDOS.BAS still "needs improvemnt", as the saying goes.

                Code:
                'SHAREWIN.BAS
                'Freeware, Public Domain, by Emil Menzel & Petr Schreiber
                'Compile in PBWIN (we developed it in ver 9.01)
                $COMPILE EXE
                $DIM ALL
                $INCLUDE ONCE "Win32api.INC"
                
                TYPE JoyInfoType
                  Time AS LONG 'Windows time, in millisec
                
                  'Joystick: X,Y,Z readings range from 0 to 65536; center=32767
                  'Calibrate your joystick with Windows Start/ControlPanel/Game Controllers
                  JX AS LONG 'joystick X axis
                  JY AS LONG 'joystick Y
                  JZ AS LONG 'joystick Z. will read 0 if your joystick is not 3-D
                  JB AS LONG 'joystick button(s) status
                
                  'Mouse readings from Win32 api can range from 0 to max resolution of your Display,
                  'as set by Windows Start/ControlPanel/Display/Settings
                  MX AS LONG 'Mouse X, on screen as a whole, according to Windows
                  MY AS LONG 'Mouse Y, on screen as a whole, according to Windows
                  MB AS LONG 'Mouse button(s) status
                
                  'Keyboard: Status according to win api function GetKeyState
                  'This does not include Shift state, etc.
                  ' ("Needs improvement", most teachers would say)
                  KyBd AS LONG
                  'Add keyboard shift status, etc here if you wish
                  'Add serial port,
                  'and old gameport status here too, as you wish
                
                  ID AS SINGLE 'identify which program read or wrote to the .DTA last
                
                  'Error Messages, &/or commands from the PBDOS program, to be executed by
                  'the PBCC program.
                  Message AS STRING * 30 'use fixed strings for all messages, to keep
                  'the .DTA file lines exactly equal in length
                
                END TYPE
                
                DECLARE SUB Sleeper(timeinsec AS SINGLE) 'for PBDOS
                DECLARE SUB Play(SynAsync AS INTEGER, WavFileName AS STRING) 'for PBCC/PBWIN
                DECLARE FUNCTION KeyStat() AS LONG 'for PBCC/PBWIN
                DECLARE FUNCTION PBMAIN() AS LONG
                
                '''PRINT PBMAIN 'un-REM for PBDOS
                
                FUNCTION PBMAIN () AS LONG
                  DIM hWnd AS DWORD
                  DIM hFont AS DWORD
                
                  FONT NEW "Fixedsys" TO hFont
                
                  GRAPHIC WINDOW "Emil", 1, 1, 640, 480 TO hWnd
                  GRAPHIC ATTACH hWnd, 0
                  GRAPHIC SET FONT hFont
                  GRAPHIC CLEAR %BLACK
                  GRAPHIC COLOR %WHITE, %BLACK
                
                  DIM Jinfo AS JoyInfoType 'room for identifier and all member elements
                  DIM JS AS JOYINFO 'JoyInfo is defined in win api --x,y,z status of joystick + buttons code
                  'At least in PBCC, JS can also be treated as a string
                  '4 bytes for each of the various LONG integers
                  'This info can be passed to other subroutines in a single 16 byte string,
                
                  DIM pt AS PointAPi ' as defined in win api -- x,y of (e.g.) Mouse
                
                  DIM ii AS LONG
                  DIM StickError AS LONG
                  DIM Count0 AS QUAD
                  DIM Count1 AS QUAD
                  DIM t AS SINGLE
                  DIM identifier AS SINGLE
                  DIM ky AS STRING
                  DIM A AS STRING
                  DIM DataFileName AS STRING
                
                  RANDOMIZE TIMER
                  t=TIMER 'use TIX to get quad identifier guaranteed unique.
                  '(TIMER usually okay too unless exe's run < 18/th sec. apart)
                  DO: LOOP UNTIL TIMER > t
                  t=TIMER
                  identifier = t 'give this exe the unique identifier
                  DataFileName ="c:\shar.dta" 'Warning: SHAREDOS.EXE can't read long file names
                  KILL DataFileName 'clear previous test runs
                
                  Jinfo.ID = identifier 'put unique identifier in the data
                  OPEN DataFileName FOR BINARY LOCK SHARED AS #1 'be sure to make SHARED
                  PUT #1,, Jinfo 'initialize. write opening string
                
                 DIM flagInstat AS LONG
                 DO UNTIL ky$ = CHR$(27) OR INSTR(Jinfo.Message,"QUIT")= 1
                 '--------Here is the actual sharing code----------------------------------------------
                
                  DO UNTIL flagINSTAT 'The INSTAT check is for debug only.
                  'I.e., press any key to read the current Counts
                
                  GRAPHIC INSTAT TO flagINSTAT
                  SEEK #1, 1 'seek to beginning
                  GET #1,, Jinfo 'read in whole UDT
                  IF Jinfo.ID = identifier THEN 'if it's from this exe, it's not our turn yet, so iterate after short sleep
                  SLEEP 10 'For PBDOS program(s) CALL Sleeper(timeInSec) instead
                  'Adjust SLEEP time for optimal performance (for your own purposes)
                  'SLEEP 0 is fine ... to test max speed, anyway
                  INCR Count0 'use for debugging or test only
                  ITERATE DO
                  ELSE
                  INCR Count1 'use for debug or test only
                  GOSUB ProcessInfo
                  '''Jinfo.ID = identifier 'I moved this line into the GOSUB
                  SEEK #1, 1 'seek to beginning
                  PUT #1,, Jinfo 'and write it
                  EXIT DO
                  END IF
                  LOOP
                 '---------End of the actual sharing code----------------------------------------------
                  GRAPHIC INKEY$ TO ky$
                  GOSUB ShowInfo
                  'make a click... A good way (in debugging) to tell how fast the program is running
                  'try both SyncAsync=0 & =1
                  '''CAll Play (1, "SOUND111.WAV") 'see Windows WAV file collection
                 LOOP
                
                 CLOSE #1
                 IF DIR$(DataFileName)<>"" THEN KILL DataFileName 'delete data file
                 GRAPHIC PRINT "Done in" & STR$(ROUND(TIMER - t, 3)) & " sec"
                 GRAPHIC PRINT "Press any key"
                
                 GRAPHIC WAITKEY$ 'for PBDOS use ky$ = INPUT$(1)
                 EXIT FUNCTION
                
                 '===== GOSUBs ================================
                  ProcessInfo:
                  'First read the Message from the other program & act on it
                  'add your own code here
                  '& post appropriate Messages for the other program
                  'Get PBCC to do what PBDOS can't do, or can't do as well.
                  'See, for starters, the list given on http://sourceforge.net
                  'in its discussion of ntvdm.exe. Running DLLs & SHELLing without using
                  'DOS cmd.exe would be also be relatively easy pieces.
                
                  'Next,
                  A$ = UCASE$(TRIM$(Jinfo.Message))
                  IF INSTR(A$, ".WAV") THEN CALL Play(0,A$)
                  Jinfo.Message = "ok" 'clear out old messages. New ones could be posted too
                
                  'Get the current status of Windows keybord, clock,joystick & mouse with win api's
                  Jinfo.KyBd = KeyStat 'check keyboard & mouse buttons
                  'Note: this is regardless of which window has the focus now
                  Jinfo.Time = GetTickCount 'win api current time
                  StickError = joyGetPos(0,JS) 'win api...reads stick#0
                  IF StickError THEN Jinfo.Message = "StickError# "+STR$(StickError)
                
                  Jinfo.JX = JS.wXpos
                  Jinfo.JY = JS.wYpos
                  Jinfo.JZ = JS.wZpos
                  Jinfo.JB = JS.wButtons
                  GetCursorPos Pt 'win api mouse pos
                  Jinfo.Mx = Pt.x
                  Jinfo.My = Pt.y
                
                  'better yet, get MouseButton status from Win32 api functions forbuttons, instead of this way
                  Jinfo.MB = Jinfo.KyBd
                  IF Jinfo.MB > 2 THEN Jinfo.MB = 0 'assuming max of 2 buttons
                
                  '''ScreenToClient hWin, pt 'win api mouse pos on whichever window has the focus
                  'could add this info too
                  IF Jinfo.KyBd THEN
                  GRAPHIC INKEY$ TO ky$ 'keypress, if CONSOLE of this program has Windows focus
                  IF ky$=CHR$(27) THEN Jinfo.Message = "QUIT"
                  'or add your own code for handling this
                  'ignore (at least here) keypresses on any other windows
                  END IF
                  'IMPORTANT! if you don't call this GOSUB, put the next line in the main loop, where John Gleason had it
                  Jinfo.ID = identifier 'otherwise, our turn to write so set ID to our identifier
                
                  RETURN
                
                  ShowInfo:
                  Graphic_Locate (10,1)
                  GRAPHIC PRINT "Time "+STR$(Jinfo.Time)+SPACE$(5)
                  GRAPHIC PRINT " JX "+ STR$(Jinfo.JX)+SPACE$(5)
                  GRAPHIC PRINT " JY "+STR$(Jinfo.JY)+SPACE$(5)
                  GRAPHIC PRINT " JZ "+STR$(Jinfo.JZ)+SPACE$(5)
                  GRAPHIC PRINT " JB "+STR$(Jinfo.JB)+SPACE$(5)
                  GRAPHIC PRINT " MX "+STR$(Jinfo.MX)+SPACE$(5)
                  GRAPHIC PRINT " MY "+STR$(Jinfo.MY)+SPACE$(5)
                  GRAPHIC PRINT " MB "+STR$(Jinfo.MB)+SPACE$(5)
                  GRAPHIC PRINT "KyBd "+STR$(Jinfo.Kybd)+SPACE$(5)
                  GRAPHIC PRINT " ID "+STR$(Jinfo.ID)
                  GRAPHIC PRINT " Msg "+Jinfo.Message+"|"
                
                  Graphic_Locate (23, 1)
                  A$="Count0"+STR$(Count0)+ " Count1" + STR$(Count1)+ " ID# "+ STR$(identifier)
                  GRAPHIC PRINT A$
                  RETURN
                END FUNCTION
                
                ' -- No 100% perfect, but usable
                SUB Graphic_Locate(y AS LONG, x AS LONG)
                 LOCAL cx, cy AS LONG
                
                 GRAPHIC TEXT SIZE "A" TO cx, cy
                
                 GRAPHIC SET POS (cx*(x-1)+1, cy*(y-1)+1)
                
                END SUB
                
                $IF 0
                'use for PBDOS programs only
                SUB Sleeper (SleepTime AS SINGLE)
                  'release a time slice
                  'ASM code from PB Support
                  DIM t AS SINGLE
                  DIM iswindows AS INTEGER
                
                  iswindows% = ISTRUE BIT(pbvhost,8)
                  IF UCASE$(ENVIRON$("os")) = "WINDOWS_NT" THEN iswindows% = -1
                
                  t=TIMER + SleepTime
                  DO
                  IF iswindows% THEN
                  ! push ds
                  ! mov ax, &h1680
                  ! int &h2f
                  ! pop ds
                  END IF
                  LOOP UNTIL TIMER > t
                END SUB
                
                $ENDIF
                
                'PB INKEY$ does not work on a graphics window.
                'KeyStat does -- albeit the returned keycodes are not all the same as INKEY$
                'It "needs work", PB gurus and indows gurus will say
                'But I leave it here as I posted it in 2005 in a thread called "NagBox"
                'Use in PBCC/PBWIN only; REM-out or delete for PBDOS
                FUNCTION keyStat() AS LONG
                  LOCAL I,ks AS LONG
                  DIM kb(255) AS STATIC BYTE
                  GetKeyBoardState kb(0) 'win api
                  FOR I=0 TO 255 'or .. ASC("A") to ASC("Z")
                  ks=GetKeyState(I) 'win api
                  IF ks<0 THEN EXIT FOR
                  NEXT
                  '''SLEEP 50 'watch out! fast-repeating keys
                  IF I>255 THEN I=0
                  FUNCTION=I
                END FUNCTION
                
                'Play a .WAV file (for PBCC/PBWIN only)
                'from a post by Mike Doty, on PB Forums, June 2009
                SUB Play(syncOrAsync AS INTEGER, sFileName AS STRING) EXPORT
                 LOCAL zFileName AS ASCIIZ * 128
                 IF LEN(sFileName) = 0 THEN sFileName = "tada"
                 zFileName = sFileName + $NUL
                 IF SyncOrAsync <>0 THEN SyncOrAsync = 1
                 CALL PlaySound(zFileName, 0% , syncOrAsync) ' sync=0=play sound until done
                  'async=1=start sound but don't wait
                END SUB
                Last edited by Emil Menzel; 5 Aug 2009, 08:51 PM.

                Comment


                • #9
                  TCP Communication fpr DOS programs

                  Take a look at:


                  Maybe it helps!

                  Greetings from austria,
                  Reinhard Böck

                  Comment


                  • #10
                    Reinhard:
                    Thank you. I prefer not to use a third-party external program, but since this one does give source code it might help to clarify some of the issues.

                    I'm going to take a break from ShareDOS for a while, to work on a different program, and to study TCP, etc. Will post again if & when I come up with something better. But in the meantime, the potential significance (at least for PBDOS programmers) of being able to communicate effectively between PBDOS and PBCC/PBWIN should not be underestimated!

                    Comment


                    • #11
                      STDIN and STDOUT may also be used.
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Michael:
                        I do not know what you mean. Please explain.

                        Comment


                        • #13
                          The STDIN and STDOUT handles are part of all MS-DOS and PB/CC (#CONSOLE ON) programs.

                          And, you have easy-to-use STDIN and STDOUT functions in both.

                          That is, these conduits are options for exchanging data between a PB/CC and PB/DOS program.
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment

                          Working...
                          X