'===========================================================================
' Subject: MORE PEEK AND POKE ROUTINES        Date: 01-11-96 (09:20)       
'  Author: Brian Roche                        Code: QB, QBasic, PDS        
'  Origin: FidoNet QUIK_BAS Echo            Packet: MEMORY.ABC
'===========================================================================
' > Does any one have a list of all those area where you Poke and Peek;
' > what they mean.

' *All* those areas ? Well, here's a list of different stuff like 
' that, that I keep layin' around...

' ======== ROM BIOS STUFF ===================================
 To use any of the Addresses below, you have to put yourself into
 The ROM BIOS Data Area, like so: DEF SEG=&H40 
 (Make Sure to specify DEF SEG when your'e done!)

 PEEK &H00      -  RS232 Addresses on your IBM PC.
                  (Number of Addresses = How many Com Ports you have)
 PEEK &H08      -  Printer Addresses on your IBM PC.
                  (Number of Printer Addresses=Number of Printers)
 PEEK &H10      -  Equipment Flag.
                  This Integer has 16 different values - each having
                  a different meaning:
                  Bit 0 -  Machine has Floppy Drives
                  Bit 2,3 - Ram Size (00=16K 10=32K 01=48K 11=64K)
                  Bit 4,5 - Video Mode 
                            00=Unused
                            10=40x25 Color
                            01=80x25 Color
                            11=80x25 Mono
                  Bit 6,7 - Number of Floppy Drives
                            (If Bit 0 = 1)
                            00=1 10=2 01=3 11=4
                  Bit 9,10,11 - Number of RS232 Cards attached
                  Bit 12  - Game I/O Attached
                  Bit 14,15  - Number of Printers 
     &H13      -  Memory Size in Kilobytes.
     &H17      -  Keyboard Flag 
                  This Integer has 16 bits fields, as well, for the KeyBoard
                  Byte 1:
                  &H80 - Insert On
                  &H40 - Caps Lock changed
                  &H20 - Num Lock changed
                  &H10 - Scroll Lock changed
                  &H08 - Alternate Shift pressed
                  &H04 - Control Shift key pressed
                  &H02 - Left Shift key pressed
                  &H01 - Right Shift key pressed
                  Byte 2;
                  &H80 - Insert Key is pressed
                  &H40 - Caps Lock Key is pressed
                  &H20 - Num Lock Key is pressed
                  &H10 - Scroll Lock key is pressed
                  &H08 - Suspend key has been toggled
     &H49      -  Current Screen mode
                  &H00 - 40x25 BW
                  &H01 - 40x25 Color
                  &H02 - 80x25 BW
                  &H03 - 80x25 Color
                  &H04 - 320x200 Color
                  &H05 - 320x200 BW
                  &H06 - 640x200 BW
     &H4A      -  Number of Screen columns
     &H50      -  Cursor Position 
     &H60      -  Cursor mode
     &H6C      -  Low word of Timer count
     &H6E      -  High word of Timer count

     ' The next two below I believe have been moved since the XT ..

     &HFA6E    -  Beginning of character regen memory
     &HFF53    -  PRTSC routine address
 ======================= End of ROM BIOS Peeks =============================
   DEF SEG=&HB800 - Color Monitor memory
   DEF SEG=&HA000 - B&W Monitor memory
 =========================================================================
 '.....  A Coupla Real Routines you could use in your programs...

 ' To Read/Find the PSP ...
   DO
    Inchar$=CHR$(PEEK &H81+N)
    PSP$=PSP$+Inchar$
    N=N+1
   LOOP UNTIL INCHAR$=CHR$(&H0D)
  '===================================================================
  ' Machine Independent delay ..
   Pause%=8        ' Number of Clock Ticks to Wait
   Def Seg = 0
     Do Until Pause% < 1
       CurrentTick% = Peek(&H46C)
       Do While CurrentTick% = Peek(&H46C):LOOP
       Pause%=Pause% - 1
    Loop
   Def Seg
  (I'm pretty sure this one's from Joe Negron..)
 '===================================================================
  ' ReBoot the computer ..
    DEF SEG = &HFFFF
    CALL Absolute(0)
 '===================================================================
 ' Reset the KeyBoard
   DEF SEG = 64
   DO
   FOR c = 0 TO 1
     FOR b = 0 TO 1
       FOR a = 0 TO 1
         POKE 23, a * 16 + b * 32 + c * 64
         IF INKEY$ > "" THEN POKE 23, 0: END
         FOR delay = 1 TO 12000: NEXT
       NEXT
     NEXT
   NEXT
   LOOP
 '===================================================================
 ' Toggle the KeyBoard lights ..
 ' Should use keyBoard clear routine above, first ..
 DEF SEG = 64
 POKE 23, 32
 DO
   a = (a MOD 96) + 48
   FOR i = 1 TO 2
     POKE 23, PEEK(23) XOR a
     IF INKEY$ > "" THEN EXIT DO
     FOR delay = 1 TO 6500: NEXT
   NEXT
 LOOP
 POKE 23, 0
 '===================================================================
 ' Save and restore a Text Window ... to restore the 'BackGround'
 ' after you're done popping up a Window in your program ..

 DEFINT A-Z
 DIM SHARED ScreenInfo(0 TO 3999)
 DECLARE SUB GetWindow (X1,Y1,X2,Y2)
 DECLARE SUB PutWindow (X1,Y1,X2,Y2)
  ' Now save a Window from text posititon 3,5 to position 24,79
  GetWindow 3,5,24,79            ' Store Screen portion in Array
  WHILE INKEY$="":WEND           ' Wait for a KeyPress
  PutWindow 3,5,24,79            ' Put Screen portion back onto Display
 END
 SUB PutWindow (X1,Y1,X2,Y2)
 DEF SEG = &HB800                               ' Assume Color Monitor
 ScreenPos = 0                                  ' Initialize Array Location
    FOR I = Y1-1 TO Y2-1                        ' Change for Partial Window
    FOR J = X1-1 to X2-1                        ' Change For Partial Window
       PokeChar = ScreenInfo(ScreenPos)         ' Get Char from array
       PokePos = (I * 160) + (J * 2)            ' Figure Screen Location
       POKE PokePos, PokeChar                   ' Poke Character to Screen
       PokeAttr = ScreenInfo(ScreenPos + 1)     ' Get Color Attrib from Array
       POKE PokePos + 1, PokeAttr               ' Poke Color Attrib to Screen
       ScreenPos = ScreenPos + 2                ' Update counter
    NEXT J, I
 DEF SEG
 END SUB
 SUB GetWindow (X1,Y1,X2,Y2)
 DEF SEG = &HB800                               ' Assume Color Monitor
 ScreenPos = 0                                  ' Initialize Array Location
    FOR I = Y1-1 TO Y2-1                        ' Change for Partial Window
    FOR J = X1-1 to X2-1                        ' Change For Partial Window
       PeekPos = (I * 160) + (J * 2)            ' Figure Screen Location
       ScreenInfo(ScreenPos) = PEEK(PeekPos)    ' Get Char from Memory
       ScreenInfo(ScreenPos+1) = PEEK(PeekPos+1)  ' Get Attrib from Memory
       ScreenPos = ScreenPos + 2                ' Update counter
    NEXT J, I
 DEF SEG
 END SUB
 '===================================================================
 ' How about using a Mouse in Interpreted QBasic ?
  DEF SEG = 0
  P207 = PEEK(207): P206 = PEEK(206)
  P205 = PEEK(205): P204 = PEEK(204)
  ' Those of you who have seen a routine of this type may notice
  ' a slight difference from the one floating around for GWBasic
  ' ... the GWBasic code would not work in QB, for some reason ...

   Mouseg = 256 * P207 + P206: Mouse% = 256 * P205 + P204 + 2
   DEF SEG = Mouseg
    ' Now see if a Mouse Driver is installed:
   IF (Mouseg OR (Mouse% - 2)) AND PEEK(Mouse% - 2) <> 207 THEN
   ELSE
    PRINT "Mouse Driver not found!": END
  END IF
 
 ' Now we want to reset the Mouse Driver :
   M1% = 0: CALL Absolute(M1%, M2%, M3%, M4%, Mouse%)
 ' And then show the Mouse Cursor ....
    M1% = 1: CALL Absolute(M1%, M2%, M3%, M4%, Mouse%)
 ' Now, we'll parse both the Mouse positions, and Button
 ' clicks in a loop .... loop aborts on first keypress ...
    M1% = 3
   DO
   CALL Absolute(M1%, M2%, M3%, M4%, Mouse%)
   IF M2% = 1 THEN LOCATE 1, 1: PRINT "Left Button Pressed "
   IF M2% = 2 THEN LOCATE 1, 1: PRINT "Right Button Pressed"
   IF M2% = 3 THEN LOCATE 1, 1: PRINT "Both Buttons Pressed"
   LOCATE 2, 1: PRINT M3%:    'Horizontal cursor position
   LOCATE 2, 6: PRINT M4%:    'Vertical cursor position
   A$ = INKEY$
 LOOP UNTIL A$ <> ""

 ' Jump out of loop once a key is pressed
 M1% = 2: CALL Absolute(M1%, M2%, M3%, M4%, Mouse%)  ' Make Cursor Invisible
 DEF SEG        ' Reset segment
 CLS : SYSTEM   ' And we're outta here ...
 '===================================================================
   ' Checking the (Returned) Errorlevel of a Shelled Program ..
   DEF SEG = 0
     ErrorLevel% = PEEK(&H4FE)
   DEF SEG
 '===================================================================
 ' Using Com 3 and 4 in Basic ..
 ' We swap the address of Com1 and Com3, or Com2 with Com4 ..
 ' Then, when you OPEN COM1:, youre really reading COM3
 ' or when you OPEN COM2:, you're really using COM4 ..

   ' Swapping COM1 & 3
        DEF SEG=64: POKE &H00,&HE8
   'Make sure to reset the Port when you're done..
      POKE &H00,&HF8

   ' Swapping COM2 & 4
       DEF SEG=64: POKE &H02,&HE8
   'Make sure to reset the Port when you're done..
      POKE &H02,&HF8
 '===================================================================

 '      QuickBasic Routine to Disable Floppy Drive "A" by
 '    Altering the Diskette Controller Infomation in the ROM
 '                  BIOS Data Segment

 ' First, Check the Machine Model Byte -
 ' This Routine should not be used (does not work) for an XT/PC
   DEF SEG = &HF000: Model = PEEK(&HFFFE)

 ' If Model Byte = 255, 254, or 251, then it is an XT or a PC, and
 ' We won't Modify the Floppy Byte.
   IF Model = 255 OR Model = 254 OR Model = 251 THEN END

 ' Get any Passed Command Line Parameter
   Param$ = LTRIM$(RTRIM$(COMMAND$))

 ' If _any_ Param is passed, then _enable_ the Floppy
 ' Drive, but if not, then We'll Disable the Drive.
   ParamLen = LEN(Param$)
   IF LEN(Param$) THEN Value = 1
  
 ' Now POKE the Value into ROM BIOS Data Area, Offset 8F
   DefSeg = &Hex40:POKE &H8F, Value:DEF SEG
 '===================================================================
 ' To force a Cold Boot with Ctrl-Alt-Del:
    POKE &H72, 0
 '===================================================================
 ' To restore Warm Boot Status :
   POKE &H72, &H1234
 '===================================================================
  ' To Disable Print-Screen Operation ..
    DEF SEG = &H50
    POKE 0, 1
    DEF SEG
 '===================================================================
  ' To Re-Enable Print-Screen Operation ..
    DEF SEG = &H50
    POKE 0, 0
    DEF SEG
 '===================================================================
 '  To read the (16 Byte) Intra-App Communications area:
    DEF SEG = &H40
     FOR I = 0 TO 15
      Status% = PEEK(&HFF + I)
      PRINT CHR$(Status%);
     NEXT
    DEF SEG
 '===================================================================
 ' Extract the ROM Version
   DEF SEG = &HF000
    PRINT "ROM Bios Date : ";
    FOR I = 0 TO 7
     PRINT CHR$(PEEK(&HFFF5 + I));
    NEXT
   PRINT

  IDByte = PEEK(&HFFFE)
   SELECT CASE IDByte
    CASE &HFF TO &HFD
     Model$ = "PC"
    CASE &HFC, &HFA
     Model$ = "286"
    CASE &HFB
     Model$ = "PC/XT"
    CASE &HF8
     Model$ = "386"
    CASE ELSE
     Model$ = "UnKnown"
    END SELECT
    PRINT "Model : "; Model$, HEX$(IDByte)
   DEF SEG
 '===================================================================
