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

  • Michael Mattias
    replied
    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.

    Leave a comment:


  • Emil Menzel
    replied
    Michael:
    I do not know what you mean. Please explain.

    Leave a comment:


  • Michael Mattias
    replied
    STDIN and STDOUT may also be used.

    Leave a comment:


  • Emil Menzel
    replied
    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!

    Leave a comment:


  • Reinhard Böck
    replied
    TCP Communication fpr DOS programs

    Take a look at:


    Maybe it helps!

    Greetings from austria,
    Reinhard Böck

    Leave a comment:


  • Emil Menzel
    replied
    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.

    Leave a comment:


  • Scott Slater
    replied
    Flush is a built-in PB Command (statement) in both DOS and CC.

    Flush {file handle number}

    Leave a comment:


  • Emil Menzel
    replied
    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.

    Leave a comment:


  • Scott Slater
    replied
    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.

    Leave a comment:


  • Emil Menzel
    replied
    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.

    Leave a comment:


  • Scott Slater
    replied
    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

    Leave a comment:


  • Scott Slater
    replied
    After your PUT statements try using a FLUSH statement. It may not be flushing the file buffers right away.

    Leave a comment:


  • 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.
Working...
X
😀
🥰
🤢
😎
😡
👍
👎