#!/usr/bin/perl -P
#
# the Author is completely unknown - this script magicaly appeared here
# I guess some monkeys have been involved in this process...
#
# Usage:  
#   install 'mga_hal_drv.o  & mga_drv.o' according to MGA's INSTALL
#
#   mgamacro.pl /location/of/mga_hal_drv.o
#
#
# Script to disable Macrovision protection in Matrox binary HAL driver
# (so it could be used with tradional home video setup:
# PC <-> Video <-> TV -  as Windows driver allows this 
# in standard operation I'm currios why the linux users should
# be prohibited to use this ??? - anyway it's not true anymore...
#

#$haldrv = "mga_hal_drv.o"; # HAL mga module filename

$haldrv = $ARGV[0]; # HAL mga module filename
if (length($haldrv) == 0)
{
    $haldrv = "mga_hal_drv.o"; # default
}
$haldrvo = "$haldrv.orig";
$haldrvn = "$haldrv.new";

# find address for function name in table
$address = 0;
open(nf, "nm $haldrv |");
while (<nf>) 
{
    ($addr, $type, $name) = split;
    if ($name eq "HSLMAVSetTVProcAmp")
    {
        $address = hex $addr;
        last;
    }
}

#
# now replace some part of the function 
#
# but the offset of this function is a little bit
# moved - so search for the real begining
# (could be probably located precisely by checking
# doc for ELF format...
#
if ($address != 0)
{
    print "HSLMAVSetTVProcAmp address: ", $address, "\n";

    open(rf, $haldrv) or die "open  $haldrv  $!";
    binmode rf;
    open(wf, "> $haldrvn") or die "open $haldrvn  $!";
    binmode wf;
    
    $modif = 0;

    # modify single bit - disable ProcAmp
    # modifing  changes in Y component of video signal  know as:
    # Macrovision protection
    
    # the upper most bit enables Macrovision
    $introold = pack("CCCC", 0xff, 0x00, 0x00, 0x00);
    $intronew = pack("CCCC", 0x7f, 0x00, 0x00, 0x00);
    #$introold = pack("CC", 0x55, 0x89);
    #$intronew = pack("CC", 0xC3, 0x89); #replace with RET

    # first block will end just near to the begining of
    # our requested function - it is made to be simple not smart
    # should be also usable for very large files... - reading in chunks
    $found = 0;
    while (sysread(rf, $buf, $address))
    {
        if ($modif == 1)
        {
            local $pos = index($buf, $introold);
            if ($pos != -1 && $pos < 300)
            {
                # only very close location
                substr($buf, $pos, length($introold)) = $intronew;
                $found = $pos;
            }
        }
        syswrite(wf, $buf, length($buf));
        $modif++;
    }
    close rf;
    close wf;
    
    if ($found > 0)
    {
        rename $haldrv, $haldrvo;
        rename $haldrvn, $haldrv;
        print "Binary driver modified.   (offset = ", $found, ")\n";
        $found = 1;
    }
    else
    {
        unlink $haldrvn;
        print "Don't know how to modify this binary driver\n";
    }
}
