VOGONS


OPL2LPT

Topic actions

Reply 200 of 566, by 640K!enough

User metadata
Rank Oldbie
Rank
Oldbie
dJOS wrote:

I havent read every page of this topic yet so apologies if this has been asked, does this need a bi-directional LPT port?

I'd like to run one from my Tandy 1000 EX which isnt bi-directional.

If I remember correctly, the device does not require a bi-directional parallel port, and does not make use of the parallel port interrupt. Does the detection tool posted at the end of page 9 of this thread find any parallel ports? If it does, then you should be able to communicate with the device. However, with 8088-class hardware, its usefulness is debatable. The TSR to re-direct accesses to the OPL2 requires a 386, so direct support will be required (using the patching tool discussed previously, for instance).

Reply 201 of 566, by dJOS

User metadata
Rank Newbie
Rank
Newbie
640K!enough wrote:
dJOS wrote:

I havent read every page of this topic yet so apologies if this has been asked, does this need a bi-directional LPT port?

I'd like to run one from my Tandy 1000 EX which isnt bi-directional.

If I remember correctly, the device does not require a bi-directional parallel port, and does not make use of the parallel port interrupt. Does the detection tool posted at the end of page 9 of this thread find any parallel ports? If it does, then you should be able to communicate with the device. However, with 8088-class hardware, its usefulness is debatable. The TSR to re-direct accesses to the OPL2 requires a 386, so direct support will be required (using the patching tool discussed previously, for instance).

Ah yes, the 386 requirement certainly renders my idea moot. Tis a shame as that would have been a fun addition to the in-built TI audio chip.

The impossible often has a kind of integrity which the merely improbable lacks.

Reply 202 of 566, by jaZz_KCS

User metadata
Rank Oldbie
Rank
Oldbie
dJOS wrote:
640K!enough wrote:
dJOS wrote:

I havent read every page of this topic yet so apologies if this has been asked, does this need a bi-directional LPT port?

I'd like to run one from my Tandy 1000 EX which isnt bi-directional.

If I remember correctly, the device does not require a bi-directional parallel port, and does not make use of the parallel port interrupt. Does the detection tool posted at the end of page 9 of this thread find any parallel ports? If it does, then you should be able to communicate with the device. However, with 8088-class hardware, its usefulness is debatable. The TSR to re-direct accesses to the OPL2 requires a 386, so direct support will be required (using the patching tool discussed previously, for instance).

Ah yes, the 386 requirement certainly renders my idea moot. Tis a shame as that would have been a fun addition to the in-built TI audio chip.

Even if it would work.... Wouldn't the workload the TSR requires make games unplayably slow?

Reply 203 of 566, by keropi

User metadata
Rank l33t++
Rank
l33t++

^ not if you use the patcher to patch the supported games - in these the extra workload is non-existent
maybe people that know how will make patches for more games in the future

🎵 🎧 PCMIDI MPU , OrpheusII , Action Rewind , Megacard and 🎶GoldLib soundcard website

Reply 204 of 566, by 640K!enough

User metadata
Rank Oldbie
Rank
Oldbie
keropi wrote:

in these the extra workload is non-existent

Not quite; as explained previously by Jepael, there is still additional overhead in the form of parallel-port I/O operations. Essentially, to get the equivalent of one write to I/O address 388H, multiple writes to the parallel port addresses are necessary to simulate what would be handled at the hardware level by the ISA bus. How that would affect performance on an 8088 (or V20) isn't clear. The best way to find out would be to try it.

Reply 205 of 566, by Scali

User metadata
Rank l33t
Rank
l33t
640K!enough wrote:

Not quite; as explained previously by Jepael, there is still additional overhead in the form of parallel-port I/O operations. Essentially, to get the equivalent of one write to I/O address 388H, multiple writes to the parallel port addresses are necessary to simulate what would be handled at the hardware level by the ISA bus. How that would affect performance on an 8088 (or V20) isn't clear. The best way to find out would be to try it.

Writes to the OPL2 registers are extremely slow.
After you write to the address port, you need to wait for 3.3 microseconds, and after you write to the data port, you need to wait for 23 microseconds.
Writing to the printer port is much faster than that, so I think it should be possible to 'hide' the extra writes in the delays required between writes to the OPL2 chip, so you get it 'for free'.
(The delays are usually done by performing 6 IO reads (in al, dx) after an address write, and 35 IO reads after a data write. You could simply remove/replace some with the LPT code).

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 206 of 566, by snow9

User metadata
Rank Newbie
Rank
Newbie
Great Hierophant wrote:
This may more likely be a PCjr. issue than an OPL2LPT issue. I assume you have expanded your PCjr. to 640KB and loaded a memory […]
Show full quote
snow9 wrote:

Hi everyone, I just made an account here to post about my OPL2LPT which recently came in the mail. I can confirm that it is working on my PCjr, which is awesome because that computer was never intended to have Adlib support or even a parallel port really.

The first game I tried was Fun Seeker's Guide, but that one gave me the following error: "0x89/3 not found." So I tried Colonel's Bequest instead and the Adlib support works beautifully on that game. I'd be playing it right now except that for some reason I can't get the PCjr graphics to load. CGA works fine and even Tandy 1000 loads in a garbled state, but when I select PCjr it just stops loading for some reason. I actually had the same issue when I tried testing Fun Seeker's Guide before patching it. Does anyone know what might be causing this?

This may more likely be a PCjr. issue than an OPL2LPT issue. I assume you have expanded your PCjr. to 640KB and loaded a memory manager to tell DOS that the PCjr. has 640KB free? You have to run the game with SIERRA.COM, not with SCIV.EXE.

How garbled are the Tandy graphics? If they appear as though only every other horizontal line is being drawn, then you can do the Tandy mod to restore the missing lines on many games.

I doubted that anyone would put up with the slowness of the PCjr. with Sierra's SCI titles for long.

It's definitely a PCjr issue, but covered all the bases you mentioned. I used to have a boxed copy of the King's Quest I remake and that ran fine, although like you said, quite slowly. Maybe it has something to do with the fact that this time I'm downloading these games from the internet? It's just so strange that specifically the PCjr setting wont load on a PCjr.

It's the kind of garbled Tandy graphics where everything turns into colorful blocks and characters, but these games should work without patching and modding since they have the PCjr option.

Reply 207 of 566, by 640K!enough

User metadata
Rank Oldbie
Rank
Oldbie
Scali wrote:
Writes to the OPL2 registers are extremely slow. After you write to the address port, you need to wait for 3.3 microseconds, and […]
Show full quote

Writes to the OPL2 registers are extremely slow.
After you write to the address port, you need to wait for 3.3 microseconds, and after you write to the data port, you need to wait for 23 microseconds.
Writing to the printer port is much faster than that, so I think it should be possible to 'hide' the extra writes in the delays required between writes to the OPL2 chip, so you get it 'for free'.
(The delays are usually done by performing 6 IO reads (in al, dx) after an address write, and 35 IO reads after a data write. You could simply remove/replace some with the LPT code).

I wasn't aware you could do that. I was under the impression that the delay began once either WR# or CS# were de-asserted, for a write. That would mean that you had to write to the LPT control port at least twice, plus the data port once before starting the delay. Am I missing something?

Reply 208 of 566, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie
640K!enough wrote:
Scali wrote:
Writes to the OPL2 registers are extremely slow. After you write to the address port, you need to wait for 3.3 microseconds, and […]
Show full quote

Writes to the OPL2 registers are extremely slow.
After you write to the address port, you need to wait for 3.3 microseconds, and after you write to the data port, you need to wait for 23 microseconds.
Writing to the printer port is much faster than that, so I think it should be possible to 'hide' the extra writes in the delays required between writes to the OPL2 chip, so you get it 'for free'.
(The delays are usually done by performing 6 IO reads (in al, dx) after an address write, and 35 IO reads after a data write. You could simply remove/replace some with the LPT code).

I wasn't aware you could do that. I was under the impression that the delay began once either WR# or CS# were de-asserted, for a write. That would mean that you had to write to the LPT control port at least twice, plus the data port once before starting the delay. Am I missing something?

Some of the delays may be embedded, but not all. Certainly address setup time can be done before controlling the CS#/WR# active.

It is not completely clear if the requirement is from end of write to end of write, of from end of write to start of write.
However, It should be easy to test how little delay is necessary before things start to go wrong.
I easily managed to get some screeching sounds from OPL2LPT plug as I initially thought it would be slow enough without delays.
So it works exactly like handled too fast when sitting on a ISA bus. With proper delays my player worked fine.

And, it should be easy to test the completely perverse case of starting the data write cycle just after address is written, but terminate it after enough delay.
Same thing for the other case as well, after data write you can start new register address write cycle before the chip is ready but terminate it after enough delay.
I would think that it won't work though, at least it won't if the register address and register data are stored in a latch from the bus. A latch would be sensitive to low level of WR#/CS#, not edge sensitive to rising edge of CS#/WR# like a flip-flop would be. So updating the latch contents during an internal write operation would corrupt the operation of course.

So I would interpret that it means clock cycles between writes. So a certain delay between the cycles, meaning, no matter how lengthy the bus cycles are, it's from end of operation to start of next operation. I could be wrong though, but at least OPL4 datasheet says that after address is written, a certain delay of clock cycles is necessary before next read or write cycle, and after data write, certain delay is necessary before next address or data write cycle. So delays between the write bus cycles.

I think I once counted this, if the OPL chip requires 12/82 clock cycle delays, that's approximately 3.35/23 microseconds, and ISA bus IO cycles assumed being about 660ns, it really is 6 and 35 IO cycles of delay. That's why on faster buses there is need for extra IO wait states.

Reply 209 of 566, by Scali

User metadata
Rank l33t
Rank
l33t

I wondered why they designed the chip like that anyway. Most chips have a bus interface that just keeps the bus busy until the chip is done. For example, I timed a write to the SN76489 chip, and that was 42 CPU cycles at 4.77 MHz. So about 11 IO cycles.
But then I thought: Perhaps Yamaha realized that keeping the bus tied up for this long would be a huge drain on the CPU. So it may be better to just release the bus as soon as the value is latched internally, and leave the delay up to the CPU side. They could do useful work in-between.

Fun fact: If you try to run TEST-SBP.EXE (the test program that comes with the Sound Blaster Pro 2.0) on an 8088 at 4.77 MHz, it can't even play the OPL3 test in realtime, because the delay code is too slow 😀

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 210 of 566, by matze79

User metadata
Rank l33t
Rank
l33t

What about using a FIFO ? do writes to the LPT and leave the Delay to the HW using some kind of mcu to do proper cycles.

https://www.retrokits.de - blog, retro projects, hdd clicker, diy soundcards etc
https://www.retroianer.de - german retro computer board

Reply 211 of 566, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie
Scali wrote:

I wondered why they designed the chip like that anyway. Most chips have a bus interface that just keeps the bus busy until the chip is done. For example, I timed a write to the SN76489 chip, and that was 42 CPU cycles at 4.77 MHz. So about 11 IO cycles.
But then I thought: Perhaps Yamaha realized that keeping the bus tied up for this long would be a huge drain on the CPU. So it may be better to just release the bus as soon as the value is latched internally, and leave the delay up to the CPU side. They could do useful work in-between.

That's because when the chips were made they were meant to be connected to simpler systems, as may CPUs or buses did not have a mechanism to lengthen bus cycles. Also, wait states (bus cycle lengthening) should be done because the peripheral/chip has a slow bus, not because the peripheral/chip itself is slow. OPL2 can easily sit on a much faster bus with 200ns write cycle, the #WR being 100ns low. So lengthening the bus cycles just was not necessary with OPL.

And, for example the IBM 5170 (AT) bus requires that the bus cycle is not lengthened for more than 2.5us, so it would be impossible to connect OPL chip to sit directly on ISA bus (without further glue logic that is).

I suppose Motorola CPUs had buses that specifically need a data acknowledge signal to end a bus cycle, but it is usually generated externally to have a fixed length for chips that don't have this. So chips like SN76489 or SAA1099 can sit on Motorola buses quite easily.

matze79 wrote:

What about using a FIFO ? do writes to the LPT and leave the Delay to the HW using some kind of mcu to do proper cycles.

It would be interesting but far more complex. However there is no point having separate FIFO, the MCU could easily handle a buffer in it's SRAM, and it would be much larger FIFO than commonly available FIFO chips would. But it would still require handling a case where FIFO is full and PC would have to wait until stuff fits into FIFO. And this could then even use less resources on PC side if an EPP port exists, but old PCs rarely have EPP.

A solution would be to tune how much the LPT code waits. Not all PCs need 6 ins and 35 ins after out. Some games calibrate a delay loop so they don't even do IO cycles while waiting. The writing code can be even dynamically generated for required delays when starting the TSR. Or, if really an MCU or other hardware is wanted, it can time the writes and give back status info when it is safe to write again, so not more time than necessary is wasted when polling. But that could be also done by the TSR, reading PIT timer count to have counted the necessary amount of ticks.

Reply 212 of 566, by Scali

User metadata
Rank l33t
Rank
l33t
dreamblaster wrote:

"custom-hacked DOSBox" !! Tell us more 😎

Yea, I've used the inpout32 library (http://www.highrez.co.uk/Downloads/InpOut32/) to redirect port writes in DOSBox to physical addresses on the host machine.
That allows you to use a physical printer port from DOSBox, for example (so I could drive the CVX4 and the OPL2LPT on a modern PC).
I may make it into a generic IO redirect patch, so people can just add a list of ports they want to redirect in their dosbox.conf, and use it for whatever they want.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 213 of 566, by SteveC

User metadata
Rank Member
Rank
Member

Just got a "new" 23 year old ThinkPad - a 360CSE (486 DX/2 50Mhz, 8MB, 344MB HDD) which doesn't have a sound card and this OPL2LPT works perfectly on it 😀

It has a faulty keyboard though where the P and ; keys don't work so had to make up a batch file copy and pasting the letters to run the commands!

YouTube: https://www.youtube.com/c/StevesTechShed
Twitter: https://twitter.com/SteveTechShed

Reply 215 of 566, by Scali

User metadata
Rank l33t
Rank
l33t

Not sure if it was mentioned before, but I couldn't find any info on how it actually works.
So here is a reference to the relevant source code: https://github.com/pdewacht/adlipt/blob/maste … l2test/OPL2.cpp

This is how you do a write to an OPL2 register. On a real AdLib you first write the register index to port 388h, then you do 6 reads for delay. Then you write the actual data byte to port 389h, and do 35 reads for delay.
This is how the LPT version looks:

	int lpt_data = lpt_base;
int lpt_ctrl = lpt_base + 2;
outp(lpt_data, reg);
outp(lpt_ctrl, PP_NOT_SELECT | PP_NOT_STROBE | PP_INIT);
outp(lpt_ctrl, PP_NOT_SELECT | PP_NOT_STROBE);
outp(lpt_ctrl, PP_NOT_SELECT | PP_NOT_STROBE | PP_INIT);
for (int i = 0; i < 6; i++) {
(volatile) inp(lpt_ctrl);
}
outp(lpt_data, data);
outp(lpt_ctrl, PP_NOT_SELECT | PP_INIT);
outp(lpt_ctrl, PP_NOT_SELECT);
outp(lpt_ctrl, PP_NOT_SELECT | PP_INIT);
for (int i = 0; i < 35; i++) {
(volatile) inp(lpt_ctrl);
}

So the basic idea is the same: first write register index, then delays, then data, and more delays.
Difference is that you don't have two separate ports. So instead the select, strobe and init line on the LPT are used to signal which of the two addresses on the OPL2 you want to write to.
First you write the value to the data port of the LPT.
As you can see, you set the not_strobe line (apparently it's reversed?) to access the address register (normally 388h), and you toggle the init-line to signal the change, so the data gets sent to the address register on the OPL2 (toggle sequence is 0x0D, 0x09, 0x0D).
You clear the not_strobe to access the data register (normally 389h), and again toggle the init-line (toggle sequence is 0x0C, 0x08, 0x0C).

That should be easy enough.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 216 of 566, by pdw

User metadata
Rank Newbie
Rank
Newbie

Hi folks. I've got a new, experimental version of the TSR that should work a lot faster on 386 CPUs. You can grab it here: https://2k38.be/adlipt/adliptx.exe
Try it with a few games and let me know how it goes!

Reply 217 of 566, by jaZz_KCS

User metadata
Rank Oldbie
Rank
Oldbie
pdw wrote:

Hi folks. I've got a new, experimental version of the TSR that should work a lot faster on 386 CPUs. You can grab it here: https://2k38.be/adlipt/adliptx.exe
Try it with a few games and let me know how it goes!

Will try it out on the PS/2 L40SX laptop (386-Sx20) and report back. I have the exact speed of the slightshow that is Keen4E with music AND sounds through TSR in my head still. As well as the slight drops of perf. using the TSR method gives in Wolf3D.

With these games on the 20Mhz machine, using the TSR or patched executable makes all the difference in terms of playability, so it should be good to test out.

Will report back.

Reply 218 of 566, by jaZz_KCS

User metadata
Rank Oldbie
Rank
Oldbie

I tried several times with the new version 0.5 test, because I couldn't believe the results and was doing something wrong, but no.

I deleted the patched executables from Keen4 and Wolf3D and renamed the uncompressed executables from the bak files back to their exe name and tried out the 0.5 TSR.

May I ask what you have changed, because at least on this machine there is now almost NO difference in speed compared to the patched version. This is a game changer.

Even Keen4E that was utterly unplayable before with sounds and music going through the TSR is now completely fluid

Reply 219 of 566, by SteveC

User metadata
Rank Member
Rank
Member

Just tried this new one on my 486 DX/2 50 Thinkpad 360CSE (PC DOS 6.3 - it says I have EMM386 you've never seen before - 4.48) and I have mixed results:
Commander Keen K6DEMO is perfect (the same as v0.4)
IPLAY/GLX212 crash trying to play MOD files (work fine just a bit quiet with v0.4)
Pinball Dreams runs noticeably slower and much louder

YouTube: https://www.youtube.com/c/StevesTechShed
Twitter: https://twitter.com/SteveTechShed