• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

The Pro Audio Spectrum 16 NuBus's YMF262 FM synthesizer...

demik

Well-known member
Thank you. Will try with 7.5. It's either a 8.1 issue or the board is checking for the PatchPanel presence and doesn't enable outputs when it's not there.

Mapped a few of the analog parts, will double check with a scope.

As for the YMF262 / YAC512 combo, U11B is the output buffer opamp for theses, which some additional circuitry tuned for this application.
As @NJRoadfan suspected its output stage indeed was traced to the mixer chip (MVA508). Outputs pins are 1 and 14 (not sure which is left and right yet)

What's weird is that there is no mixer control for that in MacOS, so you will need to do that somewhat as well in order to use...
There is a few conflicting reports around the web, as the OPL could be controlled from MIDI and some others from software, with the game "Out of this world" supposedly having support for that.
 
Last edited:

Mr. Ksoft

Well-known member
@KennyPowers, @Mr. Ksoft, What MacOS version are you using ? I seem to have trouble having sound out of the codec. MacOS control panel reports a 0kHz ramping rate (Mac OS 8.1) Alert sounds make the menu bar blink as well
7.6.1 here, though iirc I used it on 8.1 a few years ago. The software is definitely quite buggy, when first installed I see it having the sampling rate set to nothing at all (blank menu selection) but then once selected it shows the correct values. I've also had times when the system alerts still come out of the system speaker but everything else from the PAS. But on some installs I've also had everything come out of the PAS. Can't find any rhyme or reason to it. I wonder if it works better on 7.1.
 

Mr. Ksoft

Well-known member
Hey folks, bumping this cause I've been poking at it again and would like to share my findings.

I started looking at this from a different perspective, namely, disassembling the PAS16 extension. I know basically no ASM so kind of stumbling through it while reading up on it, but I figured I still may find some hints that way.

Indeed, I do think I found some stuff. The extension has two blocks of code in the DRVR resource, .PAS16 and .BD_PAS16. Conveniently, .BD_PAS16 actually has a number of modules in it that have human-readable names, which helped lead me in the right direction despite barely being able to read the code. Of particular interest to the ultimate goal here are two named FM_Bd_Status and FM_Bd_Control. FM? That sure sounds like the OPL3...

Of course I can't make sense of it. They're pretty short and I think they depend on code from other parts of the extension. Might revisit this later.

Anyway, more importantly, there's some code labeled ResetHW_SetInitialState, tied closely to two named WrtByte and RdByte. I found this very interesting because I was able to make some connections here.

ResetHW_SetInitialState:
Code:
     FE0:                                 QUAL    ResetHW_SetInitialState ; b# =72  s#1  =proc42



                                 vbu_1     VEQU  -5

                                 vbu_2     VEQU  -2

                                 vbu_3     VEQU  -1

     FE0:                                 VEND   



                                 ;-refs - Bd_Control  Bd_Open   



                                 ResetHW_SetInitialState

     FE0: 4E56 FFFA      'NV..'           LINK    A6,#-6

     FE4: 48E7 0F10      'H...'           MOVEM.L D4-D7/A3,-(A7)

     FE8: 42AC 0218      'B...'           CLR.L   $218(A4)

     FEC: 2E2C 0214      '.,..'           MOVE.L  $214(A4),D7

     FF0: 0687 0008 0000 '......'         ADDI.L  #$80000,D7

     FF6: 2C3C 0000 8000 ',<....'         MOVE.L  #$8000,D6

     FFC: 2647           '&G'             MOVEA.L D7,A3

     FFE: 1D7C 0001 FFFB 200FFFB          MOVE.B  #1,vbu_1(A6)

    1004: 41EE FFFB      200FFFB          LEA     vbu_1(A6),A0

    1008: 1010           '..'             MOVE.B  (A0),D0

    100A: A05D           '.]'             _SwapMMUMode 

    100C: 1080           '..'             MOVE.B  D0,(A0)

    100E: 6008           1001018          BRA.S   lbu_2

    1010: 26FC 8080 8080 '&..... lbu_1    MOVE.L  #$80808080,(A3)+

    1016: 5986           'Y.'             SUBQ.L  #4,D6

    1018: 4A86           'J.'    lbu_2    TST.L   D6

    101A: 6EF4           1001010          BGT     lbu_1

    101C: 41EE FFFB      200FFFB          LEA     vbu_1(A6),A0

    1020: 1010           '..'             MOVE.B  (A0),D0

    1022: A05D           '.]'             _SwapMMUMode 

    1024: 1080           '..'             MOVE.B  D0,(A0)

    1026: 2F3C 000C 0000 '/<....'         PUSH.L  #$C0000

    102C: 4267           'Bg'             CLR     -(A7)

    102E: 4EBA FAEE      1000B1E          JSR     WrtByte

    1032: 4297           'B.'             CLR.L   (A7)

    1034: A975           '.u'             _TickCount ; :LongInt

    1036: 2A1F           '*.'             POP.L   D5

    1038: 548F           'T.'             ADDQ.L  #2,A7

    103A: 42A7           'B.'    lbu_3    CLR.L   -(A7)

    103C: A975           '.u'             _TickCount ; :LongInt

    103E: 2005           ' .'             MOVE.L  D5,D0

    1040: 5880           'X.'             ADDQ.L  #4,D0

    1042: B09F           '..'             CMP.L   (A7)+,D0

    1044: 62F4           100103A          BHI     lbu_3

    1046: 2F3C 0000 9A01 '/<....'         PUSH.L  #$9A01

    104C: 3F3C 00BC      '?<..'           PUSH    #$BC

    1050: 4EBA FACC      1000B1E          JSR     WrtByte

    1054: 2EBC 0000 9A01 '......'         MOVE.L  #$9A01,(A7)

    105A: 3F3C 00E2      '?<..'           PUSH    #$E2

    105E: 4EBA FABE      1000B1E          JSR     WrtByte

    1062: 2EBC 0000 BF88 '......'         MOVE.L  #$BF88,(A7)

    1068: 3F3C 0001      '?<..'           PUSH    #1

    106C: 4EBA FAB0      1000B1E          JSR     WrtByte

    1070: 2EBC 0000 F388 '......'         MOVE.L  #$F388,(A7)

    1076: 3F3C 0040      '?<.@'           PUSH    #64

    107A: 4EBA FAA2      1000B1E          JSR     WrtByte

    107E: 2EBC 0000 F389 '......'         MOVE.L  #$F389,(A7)

    1084: 3F3C 0001      '?<..'           PUSH    #1

    1088: 4EBA FA94      1000B1E          JSR     WrtByte

    108C: 7839           'x9'             MOVEQ   #57,D4

    108E: 4878 0F8A      'Hx..'           PEA     $F8A

    1092: 3F04           '?.'             PUSH    D4

    1094: 4EBA FA88      1000B1E          JSR     WrtByte

    1098: 383C 0080      '8<..'           MOVE    #$80,D4

    109C: 2EBC 0004 0000 '......'         MOVE.L  #$40000,(A7)

    10A2: 3F04           '?.'             PUSH    D4

    10A4: 4EBA FA78      1000B1E          JSR     WrtByte

    10A8: 4878 0B8B      'Hx..'           PEA     $B8B

    10AC: 4267           'Bg'             CLR     -(A7)

    10AE: 4EBA FA6E      1000B1E          JSR     WrtByte

    10B2: 4878 0B89      'Hx..'           PEA     $B89

    10B6: 4267           'Bg'             CLR     -(A7)

    10B8: 4EBA FA64      1000B1E          JSR     WrtByte

    10BC: 4878 0B8A      'Hx..'           PEA     $B8A

    10C0: 4267           'Bg'             CLR     -(A7)

    10C2: 4EBA FA5A      1000B1E          JSR     WrtByte

    10C6: 2EBC 0000 FF8B '......'         MOVE.L  #$FF8B,(A7)

    10CC: 486E FFFE      200FFFE          PEA     vbu_2(A6)

    10D0: 4EBA FA02      1000AD4          JSR     RdByte

    10D4: 082E 0002 FFFF 200FFFF          BTST    #2,vbu_3(A6)

    10DA: 4FEF 002C      'O..,'           LEA     44(A7),A7

    10DE: 6606           10010E6          BNE.S   lbu_4

    10E0: 422C 0220      'B,. '           CLR.B   $220(A4)

    10E4: 6006           10010EC          BRA.S   lbu_5

    10E6: 197C 0001 0220 '.|...  lbu_4    MOVE.B  #1,$220(A4)

    10EC: 2F3C 0000 EF8B '/<.... lbu_5    PUSH.L  #$EF8B

    10F2: 486E FFFE      200FFFE          PEA     vbu_2(A6)

    10F6: 4EBA F9DC      1000AD4          JSR     RdByte

    10FA: 7003           'p.'             MOVEQ   #3,D0

    10FC: C06E FFFE      200FFFE          AND     vbu_2(A6),D0

    1100: 5740           'W@'             SUBQ    #3,D0

    1102: 508F           'P.'             ADDQ.L  #8,A7

    1104: 6608           100110E          BNE.S   lbu_6

    1106: 197C 0001 021F '.|....'         MOVE.B  #1,$21F(A4)

    110C: 6004           1001112          BRA.S   lbu_7

    110E: 422C 021F      'B,..'  lbu_6    CLR.B   $21F(A4)

    1112: 4A2C 0220      'J,. '  lbu_7    TST.B   $220(A4)

    1116: 660E           1001126          BNE.S   lbu_8

    1118: 4878 0B88      'Hx..'           PEA     $B88

    111C: 3F3C 0007      '?<..'           PUSH    #7

    1120: 4EBA F9FC      1000B1E          JSR     WrtByte

    1124: 5C8F           '\.'             ADDQ.L  #6,A7

    1126: 306C 028C      '0l..'  lbu_8    MOVEA   $28C(A4),A0

    112A: 2F08           '/.'             PUSH.L  A0

    112C: 2F2C 0288      '/,..'           PUSH.L  $288(A4)

    1130: 1F3C 0001      '.<..'           PUSH.B  #1

    1134: 4EBA FCCC      1000E02          JSR     SetTheSampleRate

    1138: 7874           'xt'             MOVEQ   #$74,D4

    113A: 4878 138B      'Hx..'           PEA     $138B

    113E: 3F04           '?.'             PUSH    D4

    1140: 4EBA F9DC      1000B1E          JSR     WrtByte

    1144: 4878 1389      'Hx..'           PEA     $1389

    1148: 4267           'Bg'             CLR     -(A7)

    114A: 4EBA F9D2      1000B1E          JSR     WrtByte

    114E: 4878 1389      'Hx..'           PEA     $1389

    1152: 3F3C 0040      '?<.@'           PUSH    #64

    1156: 4EBA F9C6      1000B1E          JSR     WrtByte

    115A: 2EBC 0000 BF8A '......'         MOVE.L  #$BF8A,(A7)

    1160: 3F3C 0003      '?<..'           PUSH    #3

    1164: 4EBA F9B8      1000B1E          JSR     WrtByte

    1168: 2EBC 0000 8388 '......'         MOVE.L  #$8388,(A7)

    116E: 3F3C 0002      '?<..'           PUSH    #2

    1172: 4EBA F9AA      1000B1E          JSR     WrtByte

    1176: 4217           'B.'             CLR.B   (A7)

    1178: 306C 028C      '0l..'           MOVEA   $28C(A4),A0

    117C: 2F08           '/.'             PUSH.L  A0

    117E: 4EBA FCDA      1000E5A          JSR     SetTheSampleSize

    1182: 2EBC 0000 838A '......'         MOVE.L  #$838A,(A7)

    1188: 3F3C 0018      '?<..'           PUSH    #24

    118C: 4EBA F990      1000B1E          JSR     WrtByte

    1190: 2EBC 0000 838B '......'         MOVE.L  #$838B,(A7)

    1196: 3F3C 0049      '?<.I'           PUSH    #73

    119A: 4EBA F982      1000B1E          JSR     WrtByte

    119E: 4EBA F748      10008E8          JSR     ZeroOutMixer

    11A2: 3EAC 028E      '>...'           MOVE    $28E(A4),(A7)

    11A6: 1F3C 0001      '.<..'           PUSH.B  #1

    11AA: 4EBA FCFE      1000EAA          JSR     SetStereoMono

    11AE: 2EBC 0000 F38A '......'         MOVE.L  #$F38A,(A7)

    11B4: 3F3C 0002      '?<..'           PUSH    #2

    11B8: 4EBA F964      1000B1E          JSR     WrtByte

    11BC: 4878 0B8B      'Hx..'           PEA     $B8B

    11C0: 4267           'Bg'             CLR     -(A7)

    11C2: 4EBA F95A      1000B1E          JSR     WrtByte

    11C6: 4878 0B89      'Hx..'           PEA     $B89

    11CA: 4267           'Bg'             CLR     -(A7)

    11CC: 4EBA F950      1000B1E          JSR     WrtByte

    11D0: 422C 021E      'B,..'           CLR.B   $21E(A4)

    11D4: 383C 0080      '8<..'           MOVE    #$80,D4

    11D8: 2EBC 0004 0000 '......'         MOVE.L  #$40000,(A7)

    11DE: 3F04           '?.'             PUSH    D4

    11E0: 4EBA F93C      1000B1E          JSR     WrtByte

    11E4: 383C 00F9      '8<..'           MOVE    #$F9,D4

    11E8: 4878 0B8A      'Hx..'           PEA     $B8A

    11EC: 3F04           '?.'             PUSH    D4

    11EE: 4EBA F92E      1000B1E          JSR     WrtByte

    11F2: 4878 1788      'Hx..'           PEA     $1788

    11F6: 3F3C 0010      '?<..'           PUSH    #16

    11FA: 4EBA F922      1000B1E          JSR     WrtByte

    11FE: 4878 178B      'Hx..'           PEA     $178B

    1202: 3F3C 0060      '?<.`'           PUSH    #96

    1206: 4EBA F916      1000B1E          JSR     WrtByte

    120A: 4878 178B      'Hx..'           PEA     $178B

    120E: 4267           'Bg'             CLR     -(A7)

    1210: 4EBA F90C      1000B1E          JSR     WrtByte

    1214: 4878 1B88      'Hx..'           PEA     $1B88

    1218: 3F3C 00FF      '?<..'           PUSH    #$FF

    121C: 4EBA F900      1000B1E          JSR     WrtByte

    1220: 197C 0001 0222 '.|..."'         MOVE.B  #1,$222(A4)

    1226: 4EBA 0442      100166A          JSR     proc48

    122A: 3EAC 025A      '>..Z'           MOVE    $25A(A4),(A7)

    122E: 3F2C 0258      '?,.X'           PUSH    $258(A4)

    1232: 4EBA F572      10007A6          JSR     SetTheOutVolume

    1236: 4A2C 0220      'J,. '           TST.B   $220(A4)

    123A: 4FEF 005A      'O..Z'           LEA     90(A7),A7

    123E: 6724           1001264          BEQ.S   lbu_10

    1240: 2F3C 0000 FF8B '/<....'         PUSH.L  #$FF8B

    1246: 486E FFFE      200FFFE          PEA     vbu_2(A6)

    124A: 4EBA F888      1000AD4          JSR     RdByte

    124E: 082E 0003 FFFF 200FFFF          BTST    #3,vbu_3(A6)

    1254: 508F           'P.'             ADDQ.L  #8,A7

    1256: 6606           100125E          BNE.S   lbu_9

    1258: 422C 0223      'B,.#'           CLR.B   $223(A4)

    125C: 6006           1001264          BRA.S   lbu_10

    125E: 197C 0001 0223 '.|...# lbu_9    MOVE.B  #1,$223(A4)

    1264: 4CDF 08F0      'L...'  lbu_10   MOVEM.L (A7)+,D4-D7/A3

    1268: 4E5E           'N^'             UNLK    A6

    126A: 4E75           'Nu'             RTS     





    126C: 9752 6573 6574 4857    data25   DNAME   ResetHW_SetInitialState,0,0

WrtByte:
Code:
     B1E:                                 QUAL    WrtByte ; b# =59  s#1  =proc35



                                 vbn_1     VEQU  -1

                                 param2    VEQU  8

                                 param1    VEQU  10

     B1E:                                 VEND   



                                 ;-refs - WrtMixerByte  WrtMixerVolByte 

                                 ;-       SetTheSampleRate  SetTheSampleSize 

                                 ;-       SetStereoMono  proc41   

                                 ;-       ResetHW_SetInitialState  StartupPlaying 

                                 ;-       SetupForRecord  proc45   

                                 ;-       SetupForPlayingSound 

                                 ;-       MyCInterruptHandler  MIDI_Bd_Control 

                                 ;-       myReadProc  InitMIDI 

                                 ;-       SndOutputBd_Control 



     B1E: 4E56 FFFC      'NV..'  WrtByte  LINK    A6,#-4

     B22: 48E7 0110      'H...'           MOVEM.L D7/A3,-(A7)

     B26: 266E 000A      200000A          MOVEA.L param1(A6),A3

     B2A: D7EC 0214      '....'           ADDA.L  $214(A4),A3

     B2E: 3E2E 0008      2000008          MOVE    param2(A6),D7

     B32: 1D7C 0001 FFFF 200FFFF          MOVE.B  #1,vbn_1(A6)

     B38: 41EE FFFF      200FFFF          LEA     vbn_1(A6),A0

     B3C: 1010           '..'             MOVE.B  (A0),D0

     B3E: A05D           '.]'             _SwapMMUMode 

     B40: 1080           '..'             MOVE.B  D0,(A0)

     B42: 1687           '..'             MOVE.B  D7,(A3)

     B44: 41EE FFFF      200FFFF          LEA     vbn_1(A6),A0

     B48: 1010           '..'             MOVE.B  (A0),D0

     B4A: A05D           '.]'             _SwapMMUMode 

     B4C: 1080           '..'             MOVE.B  D0,(A0)

     B4E: 4CDF 0880      'L...'           MOVEM.L (A7)+,D7/A3

     B52: 4E5E           'N^'             UNLK    A6

     B54: 4E75           'Nu'             RTS     





     B56: 8757 7274 4279 7465    data19   DNAME   WrtByte,0,0

RdByte:
Code:
     AD4:                                 QUAL    RdByte ; b# =57  s#1  =proc34



                                 vbm_1     VEQU  -1

                                 param2    VEQU  8

                                 param1    VEQU  12

     AD4:                                 VEND   



                                 ;-refs - WrtMixerByte  WrtMixerVolByte 

                                 ;-       SetStereoMono  ResetHW_SetInitialState 

                                 ;-       Bd_Control  sampleSoundVol 

                                 ;-       MIDI_Bd_Control  myReadProc 

                                 ;-       CheckForMIDIData 



     AD4: 4E56 FFFE      'NV..'  RdByte   LINK    A6,#-2

     AD8: 48E7 0110      'H...'           MOVEM.L D7/A3,-(A7)

     ADC: 266E 000C      200000C          MOVEA.L param1(A6),A3

     AE0: D7EC 0214      '....'           ADDA.L  $214(A4),A3

     AE4: 1D7C 0001 FFFF 200FFFF          MOVE.B  #1,vbm_1(A6)

     AEA: 41EE FFFF      200FFFF          LEA     vbm_1(A6),A0

     AEE: 1010           '..'             MOVE.B  (A0),D0

     AF0: A05D           '.]'             _SwapMMUMode 

     AF2: 1080           '..'             MOVE.B  D0,(A0)

     AF4: 1E13           '..'             MOVE.B  (A3),D7

     AF6: 4887           'H.'             EXT     D7

     AF8: 0247 00FF      '.G..'           ANDI    #$FF,D7

     AFC: 41EE FFFF      200FFFF          LEA     vbm_1(A6),A0

     B00: 1010           '..'             MOVE.B  (A0),D0

     B02: A05D           '.]'             _SwapMMUMode 

     B04: 1080           '..'             MOVE.B  D0,(A0)

     B06: 206E 0008      2000008          MOVEA.L param2(A6),A0

     B0A: 3087           '0.'             MOVE    D7,(A0)

     B0C: 4CDF 0880      'L...'           MOVEM.L (A7)+,D7/A3

     B10: 4E5E           'N^'             UNLK    A6

     B12: 4E75           'Nu'             RTS     





     B14: 8652 6442 7974 6500    data18   DNAME   RdByte,0,0

If you look at ResetHW_SetInitialState, there are a number of times where it moves specific numbers like 9A01 or F388 into A7, PUSHes another value, and then jumps to WrtByte. As it turns out, if you look at the PC PAS16 SDK in /PAS/INC/COMMON.H, those numbers are actually the same as the address locations for specific parts of the PAS16 (example, 9A01 is the "Master Address Pointer" and F388 is "I/O Config 1") . This indicates that the addresses are laid out identically.

I don't think these are sitting right at the base card offset, but possibly C0000 which is referenced early on. I did try doing writes using that offset from the base card address and I did actually get a result... namely I get a buzz on the speakers while doing the writes, and then the PAS16 audio dies completely until I reboot. That's more than I got before!

My continually uneducated analysis: I think this extension has a good bit of the glue in it to translate PC-style writes to what NuBus is expecting, with WrtByte and RdByte possibly doing a lot of that heavy lifting. That may explain why doing direct writes to the memory space are not working, and why direct reads are producing all 0's all the time - it may need to read in a specific way that the extension is handling.

So where does this lead? Either I need to replicate what the extension is doing in terms of byte reads/writes, or alternatively I think I need to figure out a way to communicate with the functions already present in the extension. I started looking into the latter, reading into the Toolbox Device Manager, and wrangled a bit of the example code into at least successfully opening a reference to the .BD_PAS16 driver. I got stuck there, though.
Seems there are a couple ways I can communicate with the driver, but of course we don't have a reference to work with. Looks like I can directly read/write a buffer to the driver with PBRead/PBWrite but I have no idea what it would be expecting. I'm thinking PBControl and PBStatus may be more promising as they can "send commands to the driver". Might the named functions I'm finding in the DRVR resource be exposed this way? That would allow external applications like the mixer control panel to alter the card, or those elusive PAS-enabled games to talk to it.
Thing is, good luck determining what to send to the driver... I need a csCode number apparently and those can range from 128 all the way to 32768 if we rule out the Apple reserved ranges. If there's a way to get a list of valid csCode numbers out of a driver, I might be able to get somewhere, but I haven't figured that out yet. Right now, I think my goal is to figure out if I can call ResetHW_SetInitialState using this method, which might help me get the card to output sound again after a bad write without having to reboot :)
If I can figure that out, then I would have confidence that RdByte and WrtByte may allow me to start doing direct OPL3 writes.

And so the saga continues... I think I have a lot of the puzzle pieces now. Now it's just figuring out how to put those pieces together. I'm probably getting way out of my element, but I'm trying to keep learning and get a better understanding.
 

trag

Well-known member
Not anything of note to contribute, but will note that my PAS16 did come with a copy of "Out of This World".

It always felt like it was a powerful piece of hardware with no real drivers or software to support it, back in the day.

It will be cool if you unlock its mysteries. 30 years later, it finally gets software support...
 

Mr. Ksoft

Well-known member
Not anything of note to contribute, but will note that my PAS16 did come with a copy of "Out of This World".

It always felt like it was a powerful piece of hardware with no real drivers or software to support it, back in the day.

It will be cool if you unlock its mysteries. 30 years later, it finally gets software support...
Do you know if there was anything special about that copy? Seems like the rumor on the street is that it may have been a PAS specific version.
 

trag

Well-known member
Can you upload that copy somewhere so I can test it there ?

I will see if I can find it and hope the floppy drive is still working. I haven't tried it in a while. I know it's around here somewhere.... I may have a copy already archived to a hard drive in which case the process will be easier.
 

trag

Well-known member
Okay, I had all the disks in my floppy archive. Years ago I copied all my floppies to disk images.

I put them here:

http://sphinxgroup.org/PAS16/

Let me know if the images work. They should just be Disk Copy images. If there's a problem I can binhex them or something.

I also had an archive of the LC version of the PAS16 disks.

The %AA was the trademark emblem. I guess that's how it converts.
 

Mr. Ksoft

Well-known member
Thanks, I was able to get these images working.
The copy of Out of this World is, in fact, a specific OEM version! It's marked as version "1.0mv" (presumably mv for Media Vision). Whether that means anything for this project remains to be seen. I messed with it a bit and the sound seems exactly the same as a regular copy of the game. They do seem to have slightly different sound driver resources, but that could just be a version difference as I'm using OotW version 1.0.3. Definitely something to look into further, though.
 

demik

Well-known member
How do you use the image file ? I've been trying with DiskCopy but it doesn't like it (because no ressource fork I guess)
 
Top