


  ͻ  ͻ  ͻ ͻ  ͻ  ͻ        ͻ  ͻ
  ͻ ͼ   ͻ      ͼ     ͻ    ͼ             ͻ 
            ͼ ɼ   ɻ ɻ    ͼ                       ͼ 
            ͻ Ȼ   ͼ    ͼ           ͻ       ͻ 
  ͼ ͻ   ͼ                     ͻ   ͼ        
  ͼ  ͼ  ͼ   ͼ  ͼ        ͼ  ͼ  ͼ   ͼ



  ͻ  ͻ   ͻ  ͻ  ͻ  ͻ  ͻ  ͻ
   ͼ          ͻ    ͻ    ͻ     ͻ   ͻ ͼ
   ͻ          ͼ    ͼ            ͼ       
  ͻ           ͼ   ͼ          ͻ       
  ͼ    ͼ                      ͼ              
  ͼ  ͼ  ͼ        ͼ        ͼ  ͼ   ͼ     ͼ
























                         For more information contact: 
                                   Tom Crider 
                                 jr Newsletter
                          Box 163, Southbury, CT 06488
                                 (203) 264-1055
                             
                             Document Version 1.21
                                September  1989




       ͻ
        Section 1 - General Programming Compatibility on the IBM PCjr 
       ͼ


* There are between 300,000 and 500,000 PCjr's currently in use, many with a
  full 640K of memory and multiple diskette drives (including 3.5").


* Support for 320 x 200 16 color video and 3 voice sound can be the deciding
  factor when a PCjr owner is deciding which software package to buy.


* There are several software packages which include support for the TANDY 1000
  which have had very small, simple patches applied to obtain PCjr support.


* Any PCjr with more than 128K of memory uses an extended memory device driver
  to reconfigure memory properly and to define the size of the video buffer.
  Documentation should specify what size video buffer is required to run the
  program on the PCjr (some specific examples of what CONFIG.SYS should look
  like for the more popular device drivers would be very nice).


* The PCjr and TANDY 1000 video and sound subsystems are almost identical as is
  outlined in the sections that follow.  If a program already supports the TANDY
  1000 320 x 200 16 color video or 3 voice sound chip, then it probably could be
  adapted to the PCjr very easily.  In fact, the same routines could be used to
  support both systems by using the identification byte to branch through the
  parts of the code where there are minor differences.


* In general avoid making updates by directly accessing a port address, use the
  equivalent BIOS interrupt function where ever possible.  This is especially
  true with the video display, diskette drive and keyboard.  Since all IBM PCs
  and IBM Compatibles (such as the TANDY 1000) are compatible down to the BIOS
  call level, doing so will not effect your support of other systems in any way
  and will add the PCjr to your list of supported systems.


* If a program must modify the contents of a port, then it should always...

          in       reg,port            ;read current settings from port
          or       reg,data            ;OR in the required modification
          out      port,reg            ;write new settings back to port

  This makes sure any bits in the port other than the ones being modified are
  not accidentally changed causing problems with other hardware components.



       ͻ
        Section 2 - Programming Compatibility Summary on the IBM PCjr 
       ͼ


(01) Avoid direct updates to the MODE SELECT REGISTER port 3D8h. Instead use the
     equivalent INT 10h function 00h to change video modes (see the next section
     for more details and a simple coding example).


(02) Avoid direct updates to the COLOR SELECT REGISTER port 3D9h. Instead use
     the equivalent INT 10h function 0Bh to change color palettes (see the next
     section for more details and a simple coding example).


(03) Avoid hard coding B800h as the video buffer segment address in video modes
     requiring a 32K video buffer.  This would include the 320 x 200 16 color
     and 640 x 200 4 color graphics modes.  The PCjr relocates its video buffer
     during start up via an extended memory device driver.  While the hardware
     translates any writes to the original B800h address to the new location, it
     will wrap the second 16K of data on top of the first 16K of data, leaving a
     series of horizontal stripes on the display.  The PCjr supports a special
     set of BIOS video functions (the TANDY 1000 also supports these functions)
     to help programs to overcome this problem (see the next section for more
     details and a simple coding example).


(04) Include the following code to tell the PCjr to use the TI sound chip:

          in       al,061h             ;read current settings from port 61h
          or       al,060h             ;set switches to select TI sound chip
          out      061h,al             ;write new settings back to port 61h

     After initialization, both the TI sound chip and 8253 timer chip function
     exactly alike in the PCjr and TANDY 1000.  All programs should always
     "OR" modifications with the previous contents of the port.  Bit 4 of port
     61h can be used to disable the internal speaker when set to 1.  Bits 5-6
     of port 61h select the sound source for the PCjr as follows:

            BIT 6     BIT 5     SOUND SOURCE
            -----     -----     ------------

              0         0       8253 Timer (Standard IBM Sound Source)
              1         0       Cassette Tape Interface
              0         1       I/O Channel (Line B30h)
              1         1       TI Sound Chip



       ͻ
        Section 2 - Programming Compatibility Summary on the IBM PCjr 
       ͼ


(05) The PCjr keyboard generates an interrupt 02h, the non-maskable interrupt
     (NMI).  The NMI in turn calls interrupt 48h, which translates the 62-key
     PCjr scan codes into their corresponding 83-key PC scan codes.  Interrupt
     48h then generates a simulated PC keyboard interrupt 09h to complete the
     process.  There are two major points that should be noted:

      (a) Do NOT change the NMI vector at 0000:0008 on the PCjr.

      (b) The interrupt 09h routine on the IBM PC expects the scan code to be
          contained in port 60h while the interrupt 09h routine on the PCjr
          expects the scan code to be contained in register AL.  Therefor, if
          any application program is going to hook interrupt vector 09h, it
          must make sure it's routine preserves (PUSH / POP) or replaces (IN
          AL,060h) the scan code in register AL prior to passing control to the 
          original interrupt 09h routine.

     For Example...

      i9  proc     near                ;start of new interrupt 09h routine
          push     ax                  ;save contents of reg ax onto stack
          .                            ;
          .                            ;logic for application program...
          .                            ;
          in       al,060h             ;obtain copy of scan code in reg al
          pushf                        ;simulate BIOS interrupt flag push
          call     far ptr bios9       ;call to BIOS interrupt 09h routine
          pop      ax                  ;restore contents back into reg ax
          iret                         ;return from interrupt 09h routine
      i9  endp                         ;end of new interrupt 09h routine


(06) Verify memory is configured correctly via the PCjr extended memory device
     driver.  Simply follow all INT 10h function 00h video mode change requests
     with an INT 10h function 0Fh video mode return request and then verify the
     contents of register AL before proceeding.

     For Example...

          mov      al,009h             ;request 640x200 16 color graphics mode
          mov      ah,000h             ;request the BIOS mode change function
          int      10h                 ;make mode change via a BIOS interrupt

          mov      ah,00Fh             ;request the BIOS mode return function
          int      10h                 ;make mode return via a BIOS interrupt

          cmp      al,009h             ;was video mode change request accepted?
          jnz      viderror            ;no, branch to appropriate error routine


(07) The PCjr default BIOS video mode at start up is 00h (40 x 25 B&W). Programs
     should not make assumptions about the default video mode and should issue a
     INT 10h function 00h video mode set to ensure the display is in the proper
     video mode prior to using the video display.



       ͻ
        Section 2 - Programming Compatibility Summary on the IBM PCjr 
       ͼ


(08) There is a mistake in the PCjr Technical Reference manual BIOS comments
     section for the INT 10h function 1002h.  Registers DS:DX should contain
     the pointer to the palette register list, NOT registers ES:DX as shown.


(09) The PCjr does NOT have Direct Memory Access (DMA).  One of the bad side
     effects of this is that keyboard input is locked out during any diskette
     access.  Another side effect is that copy protection schemes that depend
     upon the speed of the diskette drive tend not to work properly.


(10) If bit 7 of register AL to 1 when requesting an INT 10h video mode change,
     then the video buffer will not be cleared when the video mode is changed.


(11) The PCjr does NOT generate a BREAK scan code for its function keys.


(12) The PCjr identification byte is FDh found at location F000:FFFE.


(13) Port compatibility between the IBM PCjr and TANDY 1000 video subsystems:

       Port        IBM PCjr                                 TANDY 1000
       ----        --------                                 ----------

       3D4 (3D0)   6845 Index Register                      Same as PCjr

       3D5 (3D1)   6845 Data Register                       Same as PCjr

       3D8         Mode Select Register on PC that does     Different!!!
                   NOT exist on PCjr, it is replaced by
                   multiple registers which are accessed
                   via the Video Gate Array at port 3DA

       3D9         Color Select Register on PC that does    Different!!!
                   NOT exist on PCjr, it is replaced by
                   multiple registers which are accessed
                   via the Video Gate Array at port 3DA

       3DA         Gate Array Address Register (for OUTs)   Different!!!
                   Video Status Register (for INs)          Different!!!

       3DE         Does NOT Exist                           Unknown Use?

       3DF         CPU / CRT Page Registers                 Same as PCjr



       ͻ
        Section 3 - Programming Compatibility Details on the IBM PCjr 
       ͼ


DON'T:

;******************************************************************************
; The following code will not work on a PCjr. The reference to 3D8 is invalid.*
;******************************************************************************

          mov      al,00Ah             ;request 320x200 4 color graphics mode
          mov      dx,003D8h           ;point at assumed Mode Select Register
          out      dx,al               ;send mode change directly to hardware


DO:

;******************************************************************************
; The following code will work on a PCjr and all other IBM compatible systems *
;******************************************************************************

          mov      al,004h             ;request 320x200 4 color graphics mode
          mov      ah,000h             ;request the BIOS mode change function
          int      10h                 ;make mode change via a BIOS interrupt








DON'T:

;******************************************************************************
; The following code will not work on a PCjr. The reference to 3D9 is invalid.*
;******************************************************************************

          mov      al,030h             ;request change over to color palette 1
          mov      dx,003D9h           ;point at assumed Color Select Register
          out      dx,al               ;send color change directly to hardware


DO:

;******************************************************************************
; The following code will work on a PCjr and all other IBM compatible systems *
;******************************************************************************

          mov      bx,00001h           ;request change over to color palette 1
          mov      ah,00Bh             ;request the BIOS color change function
          int      10h                 ;make color change via a BIOS interrupt



       ͻ
        Section 3 - Programming Compatibility Details on the IBM PCjr 
       ͼ


Avoid hard coding the segment address B800h in "MOV REG,0B800h" instructions.
Instead use a variable to hold the segment address and then initialize it to
B800h.  If a program determines its running on a PCjr via the identification
byte and changes to video mode 09h or 0Ah, then use INT 10h function 0580h to
update the variable with the actual segment address of the video buffer.

Some background information on this "problem" might help explain why you must do
this.  The PCjr contains a special hardware circuit called the Video Gate Array
(VGA) which performs a wide variety of functions in managing the PCjr's video
subsystem.  One of the functions that the VGA handles is redirecting program
references to the B800h address range to the appropriate address range in low
memory.  The VGA makes the PCjr CGA compatible.  Since the CGA only contains 16K
of physical memory, it is programmed to map the 16K address range from B8000h -
BBFFFh and BC000h - BFFFFh in to the same 16K of memory (B8000h - BBFFFh).  In
maintaining CGA compatibility, the VGA does the exact same thing in the PCjr.

This is not a problem on the PCjr when selecting a video mode that requires a
video buffer that uses 16K or less of memory, but is a problem when selecting a
video mode that requires a video buffer that uses 32K of memory.  Although the
PCjr supports a 32K buffer, as outlined above the VGA maps the second 16K of
data into the same physical memory locations as the first 16K of data.  This
produces a display image with several blank lines running through it.  The best
way to eliminate this problem is to remove all direct references to B800h and
thus eliminate the VGA address translation.  This can easily be accomplished by
issuing the appropriate video function call and determining the actual address
of the video buffer inside the PCjr.

The next couple pages contain a detailed summary of the special PCjr BIOS video
functions and a simple coding example of how to use the functions to calculate
the proper segment address.  The important thing to remember is that the CPU/CRT
page registers on the PCjr and TANDY 1000 return the memory page that contains
the video buffer, not the segment address itself.  You must multiply the value
returned by the BIOS video function by 1K (1024) in order to obtain the segment
address.  Since the video buffer must be located in the first 128K of memory, of
which memory pages 0 and 1 are used by the operating system, the available video
buffer configurations can be summarized as follows:


                      Memory Page          Segment Address
                      -----------          ---------------

                           0                  RESERVED!
                           1                  RESERVED!
                           2                    0800h
                           3                    0C00h
                           4                    1000h
                           5                    1400h
                           6                    1800h
                           7                    1C00h



BIOS Video Services - INT 10H

 AH = 05 - Select Active Display Page
 AL = New Display Page Number

On PCjr Only:

 AL = 80 - Get CPU/CRT Page Registers

 AL = 81 - Set CPU Page Register
      BL = New CPU Page Register

 AL = 82 - Set CRT Page Register
      BH = New CRT Page Register

 AL = 83 - Set CPU/CRT Page Registers
      BL = New CPU Page Register
      BH = New CRT Page Register


The CPU Page Register contains the memory page which the system is currently
writing video information in to, multiply it by 1024 to get the appropriate
video buffer segment address.


The CRT Page Register contains the memory page which the display is currently
reading video information out of. Multiply it by 1024 to get the appropriate
video buffer segment address.


Bits 0-2 of port 3DFh contain the CRT Page Register, bits 3-5 contain the CPU
Page Register, while bits 6-7 contain the Video Address Mode as shown below.

            BIT 7     BIT 6     VIDEO ADDRESS MODE
            -----     -----     ------------------

              0         0       All Alpha Modes
              0         1       Low Resolution Graphics Modes
              1         1       High Resolution Graphics Modes
              1         0       Unused - Reserved


BIOS stores a copy of the CPU/CRT page register 3DFh at location 0040:008A. It
is the data in this memory location that is used to respond to the above video
functions 058xh.  The data is stored as XXCPUCRT, where XX represents the Video
Address Mode setting.


Notes:

* This is a documented function in the PCjr Technical Reference!

* Do the desired mode change before issuing the get registers request!

* If a program uses multiple graphics pages, then the best way to change
  display pages is via the INT 10h functions 058xh.  If it must do direct
  OUTs to port 3DFh, then it should also update the data stored at memory
  location 0040:008A!



DON'T:

;******************************************************************************
; This program appears to be right, but the VGA will map the 32K buffer wrong *
;******************************************************************************

; Code Section...

          mov      al,009h             ;request 320x200 16 color graphics mode
          mov      ah,000h             ;request the BIOS mode change function
          int      10h                 ;make mode change via a BIOS interrupt
;
bypass    label    near                ;continue processing at this point...
           .
           .
           .
          mov      ax,0B800h           ;load in segment address of video buffer
          mov      es,ax               ;save address in extra segment register
           .
           .
           .


DO:

;******************************************************************************
; This code can turn a TANDY 1000 video driver in to an IBM PCjr video driver *
;******************************************************************************

; Data Section...

buffaddr  dw       0B800h              ;this variable contains buffer address

; Code Section...

          cmp      id_byte,0FDh        ;is this system identified as a PCjr?
          jne      bypass              ;no, bypass finding the buffer address
;
          mov      al,009h             ;request 320x200 16 color graphics mode
          mov      ah,000h             ;request the BIOS mode change function
          int      10h                 ;make mode change via a BIOS interrupt
;
          mov      al,080h             ;request copy of CPU/CRT page registers
          mov      ah,005h             ;request to select active display page
          int      10h                 ;obtain registers via a BIOS interrupt
          xchg     bl,bh               ;exchange bytes to isolate CRT register
          xor      bh,bh               ;clear CPU register in high order byte
          mov      ax,00400h           ;prepare to multiply register by 1024
          mul      bx                  ;multiply by 1024 for segment address
          mov      buffaddr,ax         ;save buffer address into the variable
;
bypass    label    near                ;continue processing at this point...
           .
           .
           .
          mov      ax,buffaddr         ;load in segment address of video buffer
          mov      es,ax               ;save address in extra segment register
           .
           .
           .



 

