• Please review our updated Terms and Rules here

Tandy Sound Compatible PCB

i tested multiple files from master system games, even there are a rip from a tandy sound game.
But i only get the screen filled with "invalid #" errors and some badly sounding notes in the background.
 
I've found (lame approach but...) a way to patch Rendezvous with Rama. Rendezvous with Rama is a Telarium text adventure with graphics and it supports CGA for graphics only but will play 3 voice music on a PCjr or a Tandy 1000.

The game will play PC Speaker / Tandy 3 voice based on a detection routine. I haven't figured out the PCjr detection routine as unlike the Tandy one it doesn't seem to involve just reading a memory location and comparing 1 byte. I'm also not fluent in 8088 assembly so keep this in mind.

I found however that location FC00h is read, moved to the ax register and then a cmp instruction that involves 6 bytes to compare what is read in that memory location. If 21h (Tandy model byte) is the same value read at FC00h, 3 voice music will play. So for me the easiest way to patch was to simply define the memory location as the first byte of my system BIOS and then change the byte to match my system BIOS.

So open RDV.EXE with a hex editor and edit 2 locations:

At segment 780Eh (2 bytes of memory location to be read) in RDV.exe. Default is 00 FC and here you edit to whatever location you want to be read. In my case system BIOS starts at FE00h so i change to 00 FE.

Then at segment 7817h the single byte that must match what is read at the memory location we defined. My system BIOS starts with 54h (ASCII for 'T') so that's what i patch. The original value is 21h (Tandy model byte).

I know this is a lame way to patch, but with my limited knowledge i can't do better ATM. It works though!
 
I know this is a lame way to patch, but with my limited knowledge i can't do better ATM. It works though!

Usually such checks will have some kind of conditional jump somewhere. Eg, "je/jne enableTandySound". The easiest way to patch it is to replace the conditional jump with a jump that always goes to the correct address for Tandy sound. So either you need to replace the je/jne (or whatever conditional jump they use) opcode with the opcode for 'jmp', or you need to remove the jump altogether, so it is never taken (depending on which way the logic needs to go). In which case you overwrite the jmp opcode and its operand with nop instructions.
 
Usually such checks will have some kind of conditional jump somewhere. Eg, "je/jne enableTandySound". The easiest way to patch it is to replace the conditional jump with a jump that always goes to the correct address for Tandy sound. So either you need to replace the je/jne (or whatever conditional jump they use) opcode with the opcode for 'jmp', or you need to remove the jump altogether, so it is never taken (depending on which way the logic needs to go). In which case you overwrite the jmp opcode and its operand with nop instructions.


Below is a piece of dissassembled code with IDA


Code:
seg000:760D                 mov     ax, 0FC00h
seg000:7610                 mov     es, ax
seg000:7612                 assume es:nothing
seg000:7612                 cmp     byte ptr es:0, 21h ; '!'
seg000:7618                 mov     ax, 5444h
seg000:761B                 jz      short loc_7632
seg000:761D                 mov     ax, 0F000h
seg000:7620                 mov     es, ax
seg000:7622                 assume es:nothing
seg000:7622                 xor     bh, bh
seg000:7624                 mov     bl, es:0FFFEh
seg000:7629                 not     bl
seg000:762B                 shl     bx, 1
seg000:762D                 mov     ax, cs:[bx+75EEh]

                    loc_7632:                               ; CODE XREF: sub_75F6+25j
seg000:7632                 xchg    ah, al
seg000:7634                 mov     word_B440, ax
seg000:7637                 xor     ax, ax
seg000:7639                 mov     es, ax
seg000:763B                 assume es:seg000
seg000:763B                 mov     es:word_90, offset loc_764B
seg000:7642                 mov     es:word_92, cs
seg000:7647                 pop     es
seg000:7648                 assume es:nothing
seg000:7648                 pop     bx
seg000:7649                 pop     ax
seg000:764A                 retn
seg000:764A sub_75F6        endp

Not really easy for me to figure out
 
Replace the byte at offset 781B (74) with EB. This changes the instruction from jz to jmp.
 
Replace the byte at offset 781B (74) with EB. This changes the instruction from jz to jmp.

Thanks that works great, another game patched!

Do you guys (those experienced with 8088 assembly) know the opcodes by head or do you often check listings or cheat sheets?
 
Ok so i managed to patch all Spinnaker Adventure Language games with the exception of Nine Princes in Amber.

Its strange that this game has the same Tandy detection coding routine, but changing the jz instruction to jmp does not do anything. Instead only PC Speaker music is played even with a unpatched file and DOSBox machine set to Tandy. However if i change the machine to PCjr 3 voice music starts to play. I couldn't however with the disassembled executable figure out the PCjr detection routine. There are references in code for FFFEh address, which i thought to be related to PCjr detection but i couldn't find any cmp instruction to compare to a FDh byte.

So there must be another way the game uses to detect the PCjr other than the machine ID byte.
 
The early way of checking what system model you're running on was to check the model byte at F000:FFFE. However, a Tandy 1000 fakes the model byte for a PC, so you usually have to do some additional digging and check the first byte of the BIOS ROM to see if it matches what you're expecting (in the case of Tandy 1000, 21h). Here's what typical code did circa 1986:

Code:
Case Mem[$FFFF:$000E] Of
    $FF:if mem[$f000:$c000]=$21
            then machStr:='Tandy 1000'
            else machStr:='PC';
    $FE,
    $FB:machStr:='PC/XT';
    $FD:machStr:='PCjr';
    $FC:machStr:='PC/AT';
    $FA:machStr:='PS/2 Model 30';
    $F9:machStr:='PS/2 Convertible';
    $F8:machStr:='PS/2 Model 90/95?';
    $9A:machStr:='Compaq XT or Compaq Plus';
    $2D:machStr:='Compaq PC or Compaq Deskpro';
    $30:machStr:='Sperry PC';
    $E9:machStr:='Peacock XT';
    $00:machStr:='AT&T 6300/Olivetti M24';
This wasn't sustainable, so int 15/AH=C0 was supported from 1987-ish onwards that tried to give you more information.

The full system detection code I adapted from a bazillion sources is here, if you're curious: https://github.com/MobyGamer/TOPBENCH/blob/master/TOPB_DET.PAS
 
I'm failing to patch Nine Princes in Amber.

The game doesn't play 3 voice music if the machine is Tandy. In PCjr mode it does however. Took a look into the disassembled executable game file:

Code:
seg000:8CCC sub_8CCC        proc near               ; CODE XREF: sub_7F92+40p
seg000:8CCC                 push    ax
seg000:8CCD                 push    bx
seg000:8CCE                 push    es
seg000:8CCF                 mov     ax, 40h ; '@'
seg000:8CD2                 mov     es, ax
seg000:8CD4                 assume es:nothing
seg000:8CD4                 mov     al, es:10h
seg000:8CD8                 rol     al, 1
seg000:8CDA                 rol     al, 1
seg000:8CDC                 and     al, 3
seg000:8CDE                 inc     al
seg000:8CE0                 mov     byte_B688, al
seg000:8CE3                 push    ds
seg000:8CE4                 mov     cx, 6
seg000:8CE7                 mov     si, 8CBEh
seg000:8CEA                 mov     ax, cs
seg000:8CEC                 mov     ds, ax
seg000:8CEE                 assume ds:seg000
seg000:8CEE                 mov     di, 0FFEAh
seg000:8CF1                 mov     ax, 0F000h
seg000:8CF4                 mov     es, ax
seg000:8CF6                 assume es:nothing
seg000:8CF6                 repe cmpsb
seg000:8CF8                 pop     ds
seg000:8CF9                 assume ds:dseg
seg000:8CF9                 mov     ax, 4942h
seg000:8CFC                 jz      short loc_8D2B
seg000:8CFE                 mov     ax, 0FC00h
seg000:8D01                 mov     es, ax
seg000:8D03                 assume es:nothing
seg000:8D03                 cmp     byte ptr es:0, 21h ; '!'
seg000:8D09                 mov     ax, 4F54h
seg000:8D0C                 jz      short loc_8D2B
seg000:8D0E                 mov     ax, 0F000h
seg000:8D11                 mov     es, ax
seg000:8D13                 assume es:nothing
seg000:8D13                 xor     bh, bh
seg000:8D15                 mov     bl, es:0FFFEh
seg000:8D1A                 not     bl
seg000:8D1C                 cmp     bx, 3
seg000:8D1F                 jbe     short loc_8D24
seg000:8D21                 mov     bx, 0
seg000:8D24
seg000:8D24 loc_8D24:                               ; CODE XREF: sub_8CCC+53j
seg000:8D24                 shl     bx, 1
seg000:8D26                 mov     ax, cs:[bx-733Ch]
seg000:8D2B
seg000:8D2B loc_8D2B:                               ; CODE XREF: sub_8CCC+30j
seg000:8D2B                                         ; sub_8CCC+40j
seg000:8D2B                 xchg    ah, al
seg000:8D2D                 mov     word_B67C, ax
seg000:8D30                 xor     ax, ax
seg000:8D32                 mov     es, ax
seg000:8D34                 assume es:seg000
seg000:8D34                 mov     es:word_90, offset byte_8D6A
seg000:8D3B                 mov     es:word_92, cs
seg000:8D40                 pop     es
seg000:8D41                 assume es:nothing
seg000:8D41                 pop     bx
seg000:8D42                 pop     ax
seg000:8D43                 retn
seg000:8D43 sub_8CCC        endp


This seems to be the relevant part. I tried to make it that 3 voice sound stopped working when machine was set to PCjr, so i changed the offset 8F1Fh from 76 to 77. This changed the instruction from jbe to ja. I tried it with machine set to PCjr and it didn't play 3 voice music but PC Speaker instead.

So what is needed is to make the program to always reach 8F15 and always do the jump at 8F1F.
 
You are (re-)discovering that not everyone had the same way of checking for things :)

40h:10h is the equipment list set by the BIOS; the code there is checking for how many disk drives are installed.

After that, at seg000:8CE3, it compares a 6-byte string in its own code (located at offset 8CBE) to the 6 bytes at F000:FFEA. This is where the BIOS DATE string is, in the form of xx/xx/xx. This might be the "what system am I running on" check. Without knowing what the 6 bytes are in offset 8CBE, I can't advise what it is checking for.

Do you guys (those experienced with 8088 assembly) know the opcodes by head or do you often check listings or cheat sheets?

I just checked the listing for the BIOS data area right now, and sometimes I do for opcodes, but other times I can recall them from memory just due to years of practice.
 
The early way of checking what system model you're running on was to check the model byte at F000:FFFE. However, a Tandy 1000 fakes the model byte for a PC, so you usually have to do some additional digging and check the first byte of the BIOS ROM to see if it matches what you're expecting (in the case of Tandy 1000, 21h). Here's what typical code did circa 1986:

Code:
Case Mem[$FFFF:$000E] Of
    $FF:if mem[$f000:$c000]=$21
            then machStr:='Tandy 1000'
            else machStr:='PC';
    $FE,
    $FB:machStr:='PC/XT';
    $FD:machStr:='PCjr';
    $FC:machStr:='PC/AT';
    $FA:machStr:='PS/2 Model 30';
    $F9:machStr:='PS/2 Convertible';
    $F8:machStr:='PS/2 Model 90/95?';
    $9A:machStr:='Compaq XT or Compaq Plus';
    $2D:machStr:='Compaq PC or Compaq Deskpro';
    $30:machStr:='Sperry PC';
    $E9:machStr:='Peacock XT';
    $00:machStr:='AT&T 6300/Olivetti M24';
This wasn't sustainable, so int 15/AH=C0 was supported from 1987-ish onwards that tried to give you more information.

The full system detection code I adapted from a bazillion sources is here, if you're curious: https://github.com/MobyGamer/TOPBENCH/blob/master/TOPB_DET.PAS

Hi Trixter, I don't know if you have another thread for your TOPBENCH program, so I'm writing here.
Disassembling the mouse driver for Olivetti PC1 I've found their method to detect the machines, so if you want to add it to your program is quite simple:

the two bytes @ $FFFF:$000D are:
* 44h FEh or 49h FEh for "Olivetti Prodest PC1"
* 4Ah FEh for "Olivetti Prodest PC1-HD"

so in Turbo Pascal word sound like this: (if I remember right)

Case MemW[$FFFF:$000D] Of
$FE44, $FE49: machStr:='Olivetti Prodest PC1'
$FE4A: machStr:='Olivetti Prodest PC1-HD'
end;

Or you can derive it from $FE keyword's CASE.
 
without knowing what the 6 bytes are in offset 8cbe, i can't advise what it is checking for.

Code:
90 8a 46 ff 98 3d

Also the PCjr date string starts at F000:FFF5 and its 8 bytes long. It ends right at F000:FFFD just before the FDh byte at F000:FFFE.

It seems developers wanted the 3 voice music to run exclusively on the PCjr, so even though the Tandy routine is there they somehow made it irrelevant. This is beyond my abilities. Too bad because the 3 voice music is quite allright.

The best music in this Telarium adventure series of games is IMO Dragonworld.
 
Last edited:
Hi Trixter, I don't know if you have another thread for your TOPBENCH program, so I'm writing here.

There actually is another thread for that, but thank you for the info, I'll add it to the code.

It seems developers wanted the 3 voice music to run exclusively on the PCjr, so even though the Tandy routine is there they somehow made it irrelevant. This is beyond my abilities. Too bad because the 3 voice music is quite allright.

If the goal is creating an executable that always plays the music, what is wrong with forcing PCjr detection on? IIRC the games don't use PCjr graphics, only the music. (An early PCjr surprise was running Rendevous with Rama on a PCjr and getting 3-voice sound, even though it uses CGA graphics and did not advertise any PCjr support.) Maybe I'm misunderstanding the difficulty you're running into.
 
If the goal is creating an executable that always plays the music, what is wrong with forcing PCjr detection on? IIRC the games don't use PCjr graphics, only the music. (An early PCjr surprise was running Rendevous with Rama on a PCjr and getting 3-voice sound, even though it uses CGA graphics and did not advertise any PCjr support.) Maybe I'm misunderstanding the difficulty you're running into.

You're missing my point. There are 6 Telarium games that support 3 voice music + CGA graphics:


Amazon
Dragonworld
Fahrenheit 451
Nine Princes in Amber
Perry Mason: The Case of the Mandarin Murder
Rendezvous with Rama


With the exception of Nine Princes in Amber ALL of the above games support 3 voice music on a Tandy 1000. Nine Princes in Amber seems to only play 3 voice music on a PCjr.


Dragonworld, Fahrenheit 451, Perry Mason: The Case of the Mandarin Murder and Rendezvous with Rama
were the first games i patched. With Scali and Plasmas help they suggested a better way than my patch attempt. All was needed was to change a jz instruction to a jmp and these games will now play 3 voice music on a regular PC with te Tandy sound card we are discussing in this thread. For these 4 games the Tandy detection code is pretty much the same. The following piece of code is from DragonWorld:

Code:
seg000:82DC                 push    ax
seg000:82DD                 push    bx
seg000:82DE                 push    es
seg000:82DF                 mov     ax, 40h ; '@'
seg000:82E2                 mov     es, ax
seg000:82E4                 assume es:nothing
seg000:82E4                 mov     al, es:10h
seg000:82E8                 rol     al, 1
seg000:82EA                 rol     al, 1
seg000:82EC                 and     al, 3
seg000:82EE                 inc     al
seg000:82F0                 mov     byte_1D0CE, al
seg000:82F3                 mov     ax, 0FC00h
seg000:82F6                 mov     es, ax
seg000:82F8                 assume es:nothing
seg000:82F8                 cmp     byte ptr es:0, 21h ; '!'
seg000:82FE                 mov     ax, 5444h
seg000:8301                 jz      short loc_18318
seg000:8303                 mov     ax, 0F000h
seg000:8306                 mov     es, ax
seg000:8308                 assume es:nothing
seg000:8308                 xor     bh, bh
seg000:830A                 mov     bl, es:0FFFEh
seg000:830F                 not     bl
seg000:8311                 shl     bx, 1
seg000:8313                 mov     ax, cs:[bx-7D2Ch]

and Rendezvous with Rama:

Code:
seg000:75F6                 push    ax
seg000:75F7                 push    bx
seg000:75F8                 push    es
seg000:75F9                 mov     ax, 40h ; '@'
seg000:75FC                 mov     es, ax
seg000:75FE                 assume es:nothing
seg000:75FE                 mov     al, es:10h
seg000:7602                 rol     al, 1
seg000:7604                 rol     al, 1
seg000:7606                 and     al, 3
seg000:7608                 inc     al
seg000:760A                 mov     byte_1B7B8, al
seg000:760D                 mov     ax, 0FC00h
seg000:7610                 mov     es, ax
seg000:7612                 assume es:nothing
seg000:7612                 cmp     byte ptr es:0, 21h ; '!'
seg000:7618                 mov     ax, 5444h
seg000:761B                 jz      short loc_17632
seg000:761D                 mov     ax, 0F000h
seg000:7620                 mov     es, ax
seg000:7622                 assume es:nothing
seg000:7622                 xor     bh, bh
seg000:7624                 mov     bl, es:0FFFEh
seg000:7629                 not     bl
seg000:762B                 shl     bx, 1
seg000:762D                 mov     ax, cs:[bx+75EEh]


Pretty much the same isn't it? And it's the same with Fahrenheit 451 and Peery Mason. So 4 games with similar code. Patching the jz with jmp will make these 4 games play 3 voice sound on the Tandy sound card.

Now check Nine Princes in Amber:

Code:
seg000:8CCC                 push    ax
seg000:8CCD                 push    bx
seg000:8CCE                 push    es
seg000:8CCF                 mov     ax, 40h ; '@'
seg000:8CD2                 mov     es, ax
seg000:8CD4                 assume es:nothing
seg000:8CD4                 mov     al, es:10h
seg000:8CD8                 rol     al, 1
seg000:8CDA                 rol     al, 1
seg000:8CDC                 and     al, 3
seg000:8CDE                 inc     al
seg000:8CE0                 mov     byte_1B688, al
seg000:8CE3                 push    ds
seg000:8CE4                 mov     cx, 6
seg000:8CE7                 mov     si, 8CBEh
seg000:8CEA                 mov     ax, cs
seg000:8CEC                 mov     ds, ax
seg000:8CEE                 assume ds:seg000
seg000:8CEE                 mov     di, 0FFEAh
seg000:8CF1                 mov     ax, 0F000h
seg000:8CF4                 mov     es, ax
seg000:8CF6                 assume es:nothing
seg000:8CF6                 repe cmpsb
seg000:8CF8                 pop     ds
seg000:8CF9                 assume ds:dseg
seg000:8CF9                 mov     ax, 4942h
seg000:8CFC                 jz      short loc_18D2B
seg000:8CFE                 mov     ax, 0FC00h
seg000:8D01                 mov     es, ax
seg000:8D03                 assume es:nothing
seg000:8D03                 cmp     byte ptr es:0, 21h ; '"'
seg000:8D09                 mov     ax, 4F54h
seg000:8D0C                 jz      short loc_18D2B
seg000:8D0E                 mov     ax, 0F000h
seg000:8D11                 mov     es, ax
seg000:8D13                 assume es:nothing
seg000:8D13                 xor     bh, bh
seg000:8D15                 mov     bl, es:0FFFEh
seg000:8D1A                 not     bl
seg000:8D1C                 cmp     bx, 3
seg000:8D1F                 jbe     short loc_18D24

Slightly different, but pretty much also the same, one would think that patching jz to jmp would do the trick but no...only PC Speaker music. It does have another jz before which i changed to jnz and the latter to jmp but still no go. However on a PCjr machine 3 voice music plays fine.

Now the plot thickened today when i disassembled Amazon:

Code:
seg000:879A                 push    ax
seg000:879B                 push    bx
seg000:879C                 push    es
seg000:879D                 mov     ax, 40h ; '@'
seg000:87A0                 mov     es, ax
seg000:87A2                 assume es:nothing
seg000:87A2                 mov     al, es:10h
seg000:87A6                 rol     al, 1
seg000:87A8                 rol     al, 1
seg000:87AA                 and     al, 3
seg000:87AC                 inc     al
seg000:87AE                 mov     byte_1B87E, al
seg000:87B1                 push    ds
seg000:87B2                 mov     cx, 6
seg000:87B5                 mov     si, 878Ch
seg000:87B8                 mov     ax, cs
seg000:87BA                 mov     ds, ax
seg000:87BC                 assume ds:seg000
seg000:87BC                 mov     di, 0FFEAh
seg000:87BF                 mov     ax, 0F000h
seg000:87C2                 mov     es, ax
seg000:87C4                 assume es:nothing
seg000:87C4                 repe cmpsb
seg000:87C6                 pop     ds
seg000:87C7                 assume ds:dseg
seg000:87C7                 mov     ax, 4942h
seg000:87CA                 jz      short loc_187F9
seg000:87CC                 mov     ax, 0FC00h
seg000:87CF                 mov     es, ax
seg000:87D1                 assume es:nothing
seg000:87D1                 cmp     byte ptr es:0, 21h ; '!'
seg000:87D7                 mov     ax, 5444h
seg000:87DA                 jz     short loc_187F9
seg000:87DC ; ---------------------------------------------------------------------------
seg000:87DC                 mov     ax, 0F000h
seg000:87DF                 mov     es, ax
seg000:87E1                 assume es:nothing
seg000:87E1                 xor     bh, bh
seg000:87E3                 mov     bl, es:0FFFEh
seg000:87E8                 not     bl
seg000:87EA                 cmp     bx, 3
seg000:87ED                 jbe     short loc_187F2
seg000:87EF                 mov     bx, 0

Really close to Nine Princes in Amber, so i thought that this one wasn't gonna work too. But guess what: patching jz to jmp after the Tandy detection does play 3 voice music just fine both on an emulated Tandy machine, CGA + Tandy=on and also on my XT with the Tandy Sound card.

So i don't have a clue what the hell is going on with Nine Princes of Amber. Maybe there's a bug or something in the code that affects only Tandy machines but not PCjr. So 5 Telarium games patched but Nine Princes in Amber seems to be a tough nut to crack, and with my limited knowledge i don't have a clue why 3 voice sound is broken for Tandy.
 
With the exception of Nine Princes in Amber ALL of the above games support 3 voice music on a Tandy 1000.

There's actually Tandy detection code in there too. In fact, it may blow your mind that there are three different machine checks in that code. Let's take a closer look at NPIA. I'll document the code. Here's the first one:
Code:
seg000:8CE3                 push    ds                 ;save data segment register
seg000:8CE4                 mov     cx, 6              ;get ready to compare 6 bytes
seg000:8CE7                 mov     si, 8CBEh          
seg000:8CEA                 mov     ax, cs
seg000:8CEC                 mov     ds, ax             ;ds:si = cs:8CBEh which is the
                                                       ;source of the comparison,
                                                       ;somewhere in the program code
seg000:8CEE                 mov     di, 0FFEAh
seg000:8CF1                 mov     ax, 0F000h
seg000:8CF4                 mov     es, ax             ;es:si = F000:FFEA, the
                                                       ;destination of the comparison
seg000:8CF6                 repe cmpsb                 ;compare CX bytes (6 bytes)
                            ;CMPSB subtracts the source from the destination and
                            ;stores the zero result in the zero flag.  If this
                            ;finishes with the zero flag set, all bytes compared were
                            ;identical.  If the zero flag is clear, then CX holds
                            ;the location of the byte that didn't match.

seg000:8CF8                 pop     ds                 ;restore data segment register
seg000:8CF9                 mov     ax, 4942h          ;ax = 4942h         
seg000:8CFC                 jz      short loc_18D2B    ;jump if zero flag set
                                                       ;(meaning, jump if we found
                                                       ;what we were looking for)

This feels like a check for PCjr, because it jumps to the same location as a successful Tandy check. The only way to be sure is to see what the 6 bytes at cs:8CBEh are. Oh, where's the Tandy check? Right after it:

Code:
seg000:8CFE                 mov     ax, 0FC00h
seg000:8D01                 mov     es, ax             ;es = FC00h (this is also the
                                                       ;same as F000h:C000h)
seg000:8D03                 cmp     byte ptr es:0, 21h ;check first byte of BIOS ROM
                                                       ;to see if it matches value
                                                       ;found in Tandy BIOSes
seg000:8D09                 mov     ax, 4F54h          ;ax = 4F54h
seg000:8D0C                 jz      short loc_18D2B    ;jump if zero flag set
                                                       ;(meaning, jump if we found
                                                       ;what we were looking for)

As described earlier in the thread, this is a common way to check for Tandy, by seeing if the first byte of the ROM BIOS is 21h. It jumps the same location, although with a different value in AX. It's possible that the location it jumps to determines what code to run based on what is in AX: 4942h for PCjr, or 4F54h for Tandy.

So what's the third check? Right afterwards:

Code:
seg000:8D0E                 mov     ax, 0F000h
seg000:8D11                 mov     es, ax             ;es = F000h
seg000:8D13                 xor     bh, bh             ;bh = 0
seg000:8D15                 mov     bl, es:0FFFEh      ;move es:FFFE (where the model
                                                       ;byte is stored) into bl
seg000:8D1A                 not     bl                 ;invert model byte in bl
seg000:8D1C                 cmp     bx, 3              ;see if model byte is now 3
seg000:8D1F                 jbe     short loc_18D24    ;jump if it is 3 or less

The NOT instruction to perform the inversion is only so that values of FF, FE, FD, and FC show up as 0, 1, 2, or 3. (Which is weird, they could have just compared the byte directly, but whatever.) This is their way of checking if the model byte matches FF (IBM PC, or Tandy if f000:c000=21h), FE (PC/XT), FD (PCjr), or FC (PC/AT). Then it jumps somewhere else, likely a routine that makes decisions based on these values. The code feels like it only cares if this section matches 3 (a PC/AT), possibly to alter a speed-sensitive section perhaps? I'm guessing.

I think if you wanted to FORCE PCjr, you can change the first jz to JMP. If you want to FORCE Tandy, change the second jz to JMP. These should work, unless the routine at loc_18D24 (which I can't see at the moment) does additional checks.

Does that help?
 
Curiousity got the better of me, so I decided to see what those six bytes were. I was surprised:

Code:
seg000:8CBE                 db  43h ; C
seg000:8CBF                 db  4Fh ; O
seg000:8CC0                 db  4Dh ; M
seg000:8CC1                 db  50h ; P
seg000:8CC2                 db  41h ; A
seg000:8CC3                 db  51h ; Q
seg000:8CC4                 db  42h ; B
seg000:8CC5                 db  49h ; I
seg000:8CC6                 db  54h ; T
seg000:8CC7                 db  58h ; X
seg000:8CC8                 db  52h ; R
seg000:8CC9                 db  4Ah ; J
seg000:8CCA                 db  54h ; T
seg000:8CCB                 db  41h ; A

So the first check is NOT for a PCjr but actually checking to see if it's running on a Compaq Portable! Funny! So if you change the very first jz to JMP, you are forcing the wrong detection. Change the second jz to JMP (Tandy checking) and that should work for you.
 
That won't work. It plays 3 voice music only on a PCjr, and it uses the machine ID byte after the check. That's why changing a conditional jump doesn't work.

The first two jumps are for Compaq and Tandy detection. NOP them so it always falls through to the PCjr check. Then change "not bl" to "mov bl, 2". This is the value bl would have if the machine byte was FDh (for PCjr) and then inverted.

tl;dr: Put 90h at offsets 8EFC, 8EFD, 8F0C, 8F0D and B302 at offset 8F1A.
 
Back
Top