#!/usr/bin/perl -w use warnings; use strict; my @audiotypes = qw( U8 S8 U16LSB S16LSB U16MSB S16MSB S32LSB S32MSB F32LSB F32MSB ); my %funcs; my $custom_converters = 0; sub outputHeader { print < 8) { $code = "SDL_Swap${BEorLE}${size}($val)"; } else { $code = $val; } if (($signed) and (!$float)) { $code = "((Sint${size}) $code)"; } } return "${code}"; } sub maxIntVal { my $size = shift; if ($size == 8) { return 0x7F; } elsif ($size == 16) { return 0x7FFF; } elsif ($size == 32) { return 0x7FFFFFFF; } die("bug in script.\n"); } sub getFloatToIntMult { my $size = shift; my $val = maxIntVal($size) . '.0'; $val .= 'f' if ($size < 32); return $val; } sub getIntToFloatDivBy { my $size = shift; return 'DIVBY' . maxIntVal($size); } sub getSignFlipVal { my $size = shift; if ($size == 8) { return '0x80'; } elsif ($size == 16) { return '0x8000'; } elsif ($size == 32) { return '0x80000000'; } die("bug in script.\n"); } sub buildCvtFunc { my ($from, $to) = @_; my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from); my ($tsigned, $tfloat, $tsize, $tendian, $tctype) = splittype($to); my $diffs = 0; $diffs++ if ($fsize != $tsize); $diffs++ if ($fsigned != $tsigned); $diffs++ if ($ffloat != $tfloat); $diffs++ if ($fendian ne $tendian); return if ($diffs == 0); my $hashid = "$from/$to"; if (1) { # !!! FIXME: if ($diffs > 1) { my $sym = "SDL_Convert_${from}_to_${to}"; $funcs{$hashid} = $sym; $custom_converters++; # Always unsigned for ints, for possible byteswaps. my $srctype = (($ffloat) ? 'float' : "Uint${fsize}"); print <buf + cvt->len_cvt); dst = ($tctype *) (cvt->buf + cvt->len_cvt * $mult); for (i = cvt->len_cvt / sizeof ($srctype); i; --i, --src, --dst) { EOF } else { print <buf; dst = ($tctype *) cvt->buf; for (i = cvt->len_cvt / sizeof ($srctype); i; --i, ++src, ++dst) { EOF } # Have to convert to/from float/int. # !!! FIXME: cast through double for int32<->float? my $code = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, '*src'); if ($ffloat != $tfloat) { if ($ffloat) { my $mult = getFloatToIntMult($tsize); if (!$tsigned) { # bump from -1.0f/1.0f to 0.0f/2.0f $code = "($code + 1.0f)"; } $code = "(($tctype) ($code * $mult))"; } else { # $divby will be the reciprocal, to avoid pipeline stalls # from floating point division...so multiply it. my $divby = getIntToFloatDivBy($fsize); $code = "(((float) $code) * $divby)"; if (!$fsigned) { # bump from 0.0f/2.0f to -1.0f/1.0f. $code = "($code - 1.0f)"; } } } else { # All integer conversions here. if ($fsigned != $tsigned) { my $signflipval = getSignFlipVal($fsize); $code = "(($code) ^ $signflipval)"; } my $shiftval = abs($fsize - $tsize); if ($fsize < $tsize) { $code = "((($tctype) $code) << $shiftval)"; } elsif ($fsize > $tsize) { $code = "(($tctype) ($code >> $shiftval))"; } } my $swap = getSwapFunc($tsize, $tsigned, $tfloat, $tendian, 'val'); print < $tsize) { my $divby = $fsize / $tsize; print(" cvt->len_cvt /= $divby;\n"); } elsif ($fsize < $tsize) { my $mult = $tsize / $fsize; print(" cvt->len_cvt *= $mult;\n"); } print <filters[++cvt->filter_index]) { cvt->filters[cvt->filter_index] (cvt, format); } } EOF } else { if ($fsigned != $tsigned) { $funcs{$hashid} = 'SDL_ConvertSigned'; } elsif ($ffloat != $tfloat) { $funcs{$hashid} = 'SDL_ConvertFloat'; } elsif ($fsize != $tsize) { $funcs{$hashid} = 'SDL_ConvertSize'; } elsif ($fendian ne $tendian) { $funcs{$hashid} = 'SDL_ConvertEndian'; } else { die("error in script.\n"); } } } outputHeader(); foreach (@audiotypes) { my $from = $_; foreach (@audiotypes) { my $to = $_; buildCvtFunc($from, $to); } } print <