pdewacht/adlipt

Programming documentation

vincentbernat opened this issue · 6 comments

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.

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.

Thanks!

Hey!

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


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);
        }
}```

Sorry, not tested, but that should do it.

Thanks, it works for me!