• Please review our updated Terms and Rules here

Is there a way to detect a Plantronics Colorplus card by software?

carlos12

Experienced Member
Joined
May 10, 2020
Messages
183
Location
Madrid, Spain
I read the invaluable information at seasip.info. I read on this site that the Plantronics Colorplus has a register to activate the additional plane needed to use its 16 color special mode(port 03DDh). The problem is that this register is write only. I also tried to write and read a value at the second plane adress (0BC000h), but it returns the same value also in regular CGAs.

So, Is there any way to detect a Plantronics Colorplus card by software, distinguishing it from regular CGAs?

Thank you very much for your help.
 
I mean, it's not very scientific but you could run Planet X3 and select plantronics colorplus as the video mode and see if it works? the game loads super fast on even a 4.77mhz 8088 from a 360k disk.
 
So, Is there any way to detect a Plantronics Colorplus card by software, distinguishing it from regular CGAs?
Maybe by using logic. If there is 32 kb video RAM and it's not Tandy, it can't be much else than Plantronics.
 
I also tried to write and read a value at the second plane adress (0BC000h), but it returns the same value also in regular CGAs.

A normal CGA card is not fully decoded, IE, the contents of the 16k from B8000-BBFFF also appear from BC000-BFFFF. Therefore if you write a value to BC000 it will indeed read back, but the same value should *also* read back from B8000. I assume a Plantronics in CGA-compatible mode behaves the same way, but what if you set the register to enable its special mode? Presumably those two locations would become "unlinked", IE, a write to B8000 would no longer affect BC000 and vice-versa.
 
Thank you everyone for your ideas.

Eudimorphodon: yes! You are just right! I finally managed to distinguish a Plantronics from a regular CGA. I wrote this assembly code:

Code:
	mov  ax,0BC00h
    	mov  es,ax
    	mov  di,0
	mov  al,121
	stosb                  ; Writting a random value to Plantronics second plane at 0BC00h

	mov  ax,0B800h
	mov  es,ax
	mov  di,0
  	mov  al,121
	cmp  es:[di],al
	jne   isPlantronics ; If there's a Plantronics, the value inserted at 0BC00h does not wrap into 0B800h

        ; Do whatever you want to do with a regular CGA here

isPlantronics:

        ; Plantronics code

This code must be used after assuring the card is a CGA. Other cards such as EGAs and VGAs wrap the video memory adrresses, so they could give a false positive. We must also set a regular CGA graphic mode, and writting to 03DDh port must, just as explained at seasip.info. For 320x200x16 colors I sent 16 as a value (00010000).

One thing that confused me a lot was DosBox: at least on 0.74 version, it gives a false positive as it wraps the addresses even when set on CGA mode.

Thank you for your help!
 
This code must be used after assuring the card is a CGA. Other cards such as EGAs and VGAs wrap the video memory adrresses, so they could give a false positive. We must also set a regular CGA graphic mode, and writting to 03DDh port must, just as explained at seasip.info. For 320x200x16 colors I sent 16 as a value (00010000).

One thing that confused me a lot was DosBox: at least on 0.74 version, it gives a false positive as it wraps the addresses even when set on CGA mode.

I think you can eliminate the false positives by trying to swap the address mapping of the red/green and blue/intensity pages. If that works, you can be pretty sure it is a Plantronics ColorPlus.
What could turn out to be problematic, though, is that other enhanced CGA chipsets or CGA+HGC combo chipsets use the same 3ddh register for something else.
This means that you cannot really use your code as a generic unsupervised detection routine. That is: You could, provided that your code tries to detect or rule out everything and anything in the correct order.

You could indeed use Planet X3 as a visual test, but it does not check anything before it tries to switch to Plantronics mode. It will blindly trust the user input and do funny things when the expected hardware is not there.
 
Hi, Benedikt. Thank you for your input.

I tried the procedure described above on several video cards, all of them via emulation on 86Box, and it seems to work fine. The problem, as you say, is that there are too many different cards. 86Box emulates a lot of them but for sure there are even more. But for most cases, at least with the most frequently used cards, it seems to be ok.

Detailing a bit more the process:

- First, I make sure that the program is running on a CGA, discarding EGAs, MCGAs, VGAs, HGCs et al. I use a much longer detection code, expanding the one used on the VGA Xmode Xlib, but this is a snipet of the CGA part (the program previously detects more advanced cards, so this code never gets executed on, for example, a VGA):

Code:
	mov  al,4
	mov  ah,0
	int  10h				 ; Set CGA med resolution 4 colors mode
	xor  al,al				 ; al = 0
	mov  ah,0fh		         ; Test if mode changed
	int  10h 
        cmp  al,4
        je  isCGA

- Then I activate the ColorPlus special mode
Code:
       mov dx,03DDh
       out  dx,00010000b

- I finally apply the code that I posted above

I also add a test to see if the program is running under DosBox. This part is written in C:

Code:
   bool DosBox()
   {
       struct stat buffer;

       if (stat ("Z:\\COMMAND.COM", &buffer) < 0)
           return false;
       else
           return true;
    }
If runs under DosBox, for sure it's not a Plantronics.

Anyway, in my program I give the user the option to choose whatever the mode s/he wants to use. The detection is only indicative. But the case of the Plantronics is a bit special, as my program only offers the 16 color mode if detected, in order to not confuse the user.

BTW, I just love the work you did with the additional modes for Planet X3. I'm really impressed with the 320x200x256 colors to 640x200x16 colors dithering. Would love to know more about it. Congrats!
 
FYI, the Olivetti M24 (and variants), and some compaqs, have 32K of display RAM as well. So just a simple test for 32K won't tell you if it's plantronics or not.

You probably don't need to worry about this because you don't support the M24 400-line mode. But if it becomes necessary to differentiate between plantronics, M24, TandySL/TL, etc. then this might help:

Code:
    {Key kids, let's do all sorts of extended CGA adapter detection!
    Tandy, PCjr, AT&T 6300, Compaq Portable III, you name it!}

    {First, the PCjr/Tandy family, as they have relocatable video ram.}
    {PCjr, Tandy, Tandy SL/TL code inspired by Jason Knight}
    asm
	    mov  ax,$FFFF
	    mov  es,ax
	    mov  di,$000E     { second to last byte PCjr/Tandy BIOS info area }
	    cmp  byte ptr es:[di],$FD  { ends up $FD only on the Jr. }
	    jne  @notJr
	    mov  result,1 {videoCard_pcJr}
	    jmp  @done
    @notJr:             { not junior, test for tandy }
	    cmp  byte ptr es:[di],$FF  { all tandys have $FF here }
	    jne  @notTandy
	    mov  ax,$FC00
	    mov  es,ax
	    xor  di,di
	    mov  al,$21
	    cmp  byte ptr es:[di],$21
	    jne  @notTandy
	    mov  ah,$C0
	    int  $15          { Get System Environment }
	    jnc  @tandySLTL   { early Tandys error out, TL/SL does not }
	    mov  result,2 {tandy1000}
	    jmp @done
    @tandySLTL:
	    mov  result,3 {tandySLTL}
	    jmp @done
    @notTandy:
	    mov  result,0 {all other cards eliminated, must be CGA}
    @done:
    end;

    case result of
      1:s:='IBM PCjr';
      2:s:='Tandy 1000';
      3:s:='Tandy 1000 SL/TL';
    end;

    {Now check for specific adapters based on various criteria.
    This was really tough for me; I tried all sorts of ideas to detect
    these adapters and modes, but in the end, such bit-banging is not
    safe.  A true "universal" 640x400 detector is just not possible without
    the possibility of crashing unknown hardware.}

    asm
      {First, check for AT&T/Olivetti using the model byte, which they
      have been so kind as to implement broken (returns 0000)}
      mov     ah,$C0
      int     15h          {6300 has NO 15h support in BIOS }
      jc      @ATTFound    {if CF=1, error; try to detect 6300 some other way}
      mov     ax,es:[bx+2] {grab model word}
      cmp     ax,$01FC     {See if we're on the Compaq 400-line adapter/plasma}
      je      @CompaqFound
      jmp     @error
    @CompaqFound:
      {We think we are on a Compaq Portable III.  Let's see if we can detect
      the internal plasma monitor.}
      mov     dx,1BC6h
      in      al,dx
      mov     cl,4
      shr     al,cl
      mov     result,al       {If this is plasma, result=4 if 400-line}
      jmp     @done
    @ATTFound:
      {Let's try a second check for the 6300/M24.
      Run a 6300/M24-specific BIOS INT.  If it returns info, we are SURE
      we are on a 6300/M24 and try to grab monitor ID bits from 3dah.
      ;Int 1A/AH=FEh
      ;AT&T 6300 - READ TIME AND DATE
      ;AH = FEh
      ;Return:
      ;BX = day count (0 = Jan 1, 1984)
      ;CH = hour
      ;CL = minute
      ;DH = second
      ;DL = hundredths}

      xor     cx,cx
      mov     dx,cx
      mov     ax,0fe00h
      int     1ah
      or      cx,dx            {if any bits are set anywhere, we have 6300/M24}
      jcxz    @error           {no bits?  No 6300/M24!}
      mov     dx,03dah         {a monitor ID in bits 4-5 (2=colour, 3=mono}
      in      al,dx            {If a DEB is present, bits 6 and 7 will be 0}
      mov     cl,4
      shr     al,cl            {discard regular status bits}
      test    al,00000010b     {if 2 or 3, bit 1 will be set and we have AT&T}
      jz      @error
      mov     result,al
      and     result,00000011b {mask off DEB bits}
      test    al,00001100b     {if these are unset, we have a DEB}
      jnz     @done
      or      result,10000000b {set bit 7 if DEB present}
      jmp     @done
    @error:
      mov     result,0         {must have made a mistake...?}
    @done:
    end;

    {check our results and set the string}
    case (result and $7F) of
      2:s:='AT&T/Olivetti (Color Monitor)';
      3:s:='AT&T/Olivetti (Monochrome Monitor)';
      4:s:='Compaq Portable III (Internal Plasma)';
    end;
    if (result AND $80)=$80 then s:=s+' + DEB';
 
When the M24 isn't set up for an extended video mode does it replicate the 16k wrapping behavior of plain CGA, or is the extra 16k always there?
 
By sheer coincidence, I happen to have my 6300 right next to me. Let me check...

A quick test with debug shows that the extra 16K memory is indeed active whether you're using a 32K mode or not.
 
So that is a distinction from Plantronics. Or at least the OP’s card. There were several clone chipsets that supported Plantronics emulation, I wonder how consistent they were.
 
Trixter said:
FYI, the Olivetti M24 (and variants), and some compaqs, have 32K of display RAM as well. So just a simple test for 32K won't tell you if it's plantronics or not.

You probably don't need to worry about this because you don't support the M24 400-line mode. But if it becomes necessary to differentiate between plantronics, M24, TandySL/TL, etc. then this might help:

Good point. I just checked my program with 86Box, which emulates both machines (M24 and Compaq Portable III), and you are right: I got a big false positive.

In my detection routine I already previously discard the PCjr and Tandy 1000.

I'll include your code into my detection routines. Thanks!
 
Last edited:
I also add a test to see if the program is running under DosBox. This part is written in C:

Code:
   bool DosBox()
   {
       struct stat buffer;

       if (stat ("Z:\\COMMAND.COM", &buffer) < 0)
           return false;
       else
           return true;
    }
If runs under DosBox, for sure it's not a Plantronics.

there is a safer test, look in bios starting at 0xFE00:030 + 0x60 and you will find DOSBox string as the BIOS ID.

I set my CDROM as Z: and as dump image of one of my drives, it would have a z:\command.com and not be dosbox... but these odds are low.
 
In my opinion, the DOSBox check does not really make any sense here, because technically, one could add Plantronics support to DOSBox just like it has been added to PCem.
The presence or absence of Plantronics' page swap mechanism, on the other hand, should identify a Plantronics card pretty reliably.
 
BloodyCactus said:
there is a safer test, look in bios starting at 0xFE00:030 + 0x60 and you will find DOSBox string as the BIOS ID.

Thanks! Much better.

Benedikt said:
The presence or absence of Plantronics' page swap mechanism, on the other hand, should identify a Plantronics card pretty reliably.

But how can this be done? AFAIK, the 03DDh port in the Plantronics is write only. How can the program detect that the planes has been swapped?
 
But how can this be done? AFAIK, the 03DDh port in the Plantronics is write only. How can the program detect that the planes has been swapped?

If the seasip information is accurate setting bit six on port 3DDh actually swaps the first and second 16k in memory map, IE, anything you wrote to BC000 *after* blindly trying to set a 32k Plantronics video mode (because, remember, without doing that you get the *same* 16k repeated in both slots) before you switched pages will show up at B8000 afterwards, and vice-versa. So I think the idea here is:

1: Rule out whatever else you can to try to narrow it down to being "CGA" or "Something a lot like CGA". This probably includes a test of the 16k wrapping behavior by confirming writes to B8000 affect BC000 and vice-versa.
2: Blindly try setting the 640x200x4 or 320x200x16 Plantronics mode, redo the memory test to see if the locations have become unlinked. Write a known (different) value to the two pages.
3: Set bit 6, see if those known values swap.
 
Code:
                mov al,4
                mov ah,0
                int 10h  ; Regular CGA 4 color mode

		mov  dx, 03DDh
		mov  al, 00010000b
		out   dx, al  ; Bit 4 for ColorPlus special 320x200x16 color mode
               
		mov  ax,0BC00h
      	        mov  es,ax
     	        mov  di,0
		mov  al,121    // Setting a random value on the Plantronics second plane
		stosb

		mov  ax,0B800h
		mov  es,ax
		mov  di,0
		mov  al,39     ; Random value to the first plane
		stosb

		mov  dx, 03DDh
		mov  al, 01010000b
		out   dx, al  ; Bit 6 swaps planes on the ColorPlus

		mov  ax,0B800h
		mov  es,ax
		mov  di,0
		cmp  es:[di],121   ; If ColorPlus, the value of first plane will be interchanged with
				         ; the second one

		je isPlantronics

It seems it works... Thanks!
 
Back
Top