pdewacht / adlipt

OPL2LPT utilities
77 stars 7 forks source link

Programming documentation #1

Closed vincentbernat closed 6 years ago

vincentbernat commented 6 years ago

Hey!

Do you have some notes on how to adapt code working with AdLib to code working with the OPL2LPT? This could be extracted from the driver, but since it is using some assembly foo, I am unsure to grasp the differences.

pdewacht commented 6 years ago

If it's for a DOS program, you can use this routine:

int lpt_base;

void opl2lpt_write(char reg, char data) {
        if (!lpt_base) {
                return;
        }
        int lpt_data = lpt_base;
        int lpt_ctrl = lpt_base + 2;

        /* Select OPL2 register */
        outp(lpt_data, reg);
        outp(lpt_ctrl, 13);
        outp(lpt_ctrl, 9);
        outp(lpt_ctrl, 13);

        /* Wait at least 3.3 microseconds */
        for (int i = 0; i < 6; i++) {
                (volatile) inp(lpt_ctrl);
        }

        /* Set value */
        outp(lpt_data, data);
        outp(lpt_ctrl, 12);
        outp(lpt_ctrl, 8);
        outp(lpt_ctrl, 12);

        /* Wait at least 23 microseconds */
        for (int i = 0; i < 35; i++) {
                (volatile) inp(lpt_ctrl);
        }
}

The variable lpt_base should be initialized to the base address of the parallel port, you can find that address in the BIOS Data Area (it might vary from computer to computer):

port address
LPT1 0040:0008
LPT2 0040:000A
LPT3 0040:000C

There's no method to detect the presence of an OPL2LPT.

vincentbernat commented 6 years ago

Thanks!

vincentbernat commented 6 years ago

Hey!

With the OPL3LPT, how should we write to the second register?

pdewacht commented 6 years ago


void opl3lpt_write(int reg, char data) {
        if (!lpt_base) {
                return;
        }
        int lpt_data = lpt_base;
        int lpt_ctrl = lpt_base + 2;

        /* Select OPL3 register */
        outp(lpt_data, reg & 0xFF);
        if (reg < 0x100) {
            outp(lpt_ctrl, 13);
            outp(lpt_ctrl, 9);
                outp(lpt_ctrl, 13);
        } else {
            outp(lpt_ctrl, 5);
            outp(lpt_ctrl, 1);
                outp(lpt_ctrl, 5);
        }

        /* Wait at least 3.3 microseconds */
        for (int i = 0; i < 6; i++) {
                (volatile) inp(lpt_ctrl);
        }

        /* Set value */
        outp(lpt_data, data);
        outp(lpt_ctrl, 12);
        outp(lpt_ctrl, 8);
        outp(lpt_ctrl, 12);

        /* 3.3 microseconds is sufficient here as well for OPL3 */
        for (int i = 0; i < 6; i++) {
                (volatile) inp(lpt_ctrl);
        }
}```
pdewacht commented 6 years ago

Sorry, not tested, but that should do it.

vincentbernat commented 6 years ago

Thanks, it works for me!