NetBSD/sys/arch/arm32/vidc/makemodes.awk

312 lines
7.6 KiB
Awk

# $NetBSD: makemodes.awk,v 1.1 1999/01/01 10:26:41 mark Exp $
#
# Copyright (c) 1998 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
# by Mark Brinicombe
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# This parses a Acorn monitor definition file and constructs an array of
# parameters for each mode.
# Once the file has been parsed the list of modes is examined to find modes
# that match the mode specifications specified on the command line.
# The matching mode definitions are written to stdout in the form of a C file.
# Parsing information is written to stderr.
#
#
# Syntax for using this program
#
# awk -f makemodes.awk <MDF file> <mode spec> [<mode spec> ...]
#
# where <mode spec> is
# <x>,<y>
# <x>,<y>,<f>
# <x>,<y>,<c>,<f>
#
# Note: Spaces are NOT allowed in a mode specifier
#
# where x = x resolution
# y = y resolution
# f = frame rate
# c = colour depth (16, 256, 32768, 65536)
#
BEGIN {
# Number of modes parsed and valid in the modes array.
mode = 0;
# MDF file globals
monitor = "";
dpms = 0;
# Non zero if we are translating a mode
translate = 0;
# ':' character is used to separate the tokens.
FS=":";
# Note the real number of arguments and truncate ARGC so that only the first
# argument is used as a filename.
realargc = ARGC;
ARGC=2;
}
# MDF File format
/^file_format/ {
# Currently we only understand format 1 MDF files
if ($2 != 1) {
printf("Unrecognised MDF format (%d)\n", $2);
exit;
}
}
# Monitor name
/^monitor_title/ {
monitor = $2;
}
# Monitor DPMS state
/^DPMS_state/ {
dpms = $2;
}
# Start of mode definition
/^startmode/ {
translate = 1;
}
# End of mode definition
/^endmode/ {
translate = 0;
mode = mode + 1;
}
# The mode definition name (only valid within startmode/endmode section)
/^mode_name:/ {
if (!translate)
next;
modes[mode, 0] = $2;
next;
}
# The horizontal resolution (only valid within startmode/endmode section)
/^x_res:/ {
if (!translate)
next;
modes[mode, 1] = $2;
next;
}
# The vertical resolution (only valid within startmode/endmode section)
/^y_res:/ {
if (!translate)
next;
modes[mode, 2] = $2;
next;
}
# The pixel rate (only valid within startmode/endmode section)
/^pixel_rate:/ {
if (!translate)
next;
modes[mode, 3] = $2;
next;
}
# The horizontal timings (only valid within startmode/endmode section)
/^h_timings:/ {
if (!translate)
next;
modes[mode, 4] = $2;
next;
}
# The vertical timings (only valid within startmode/endmode section)
/^v_timings:/ {
if (!translate)
next;
modes[mode, 5] = $2;
next;
}
# The sync polarity (only valid within startmode/endmode section)
/^sync_pol:/ {
if (!translate)
next;
modes[mode, 6] = $2;
next;
}
END {
#
# Now generate the C file
#
# Create the file header
printf("/*\n");
printf(" * MACHINE GENERATED: DO NOT EDIT\n");
printf(" *\n");
printf(" * Created from %s\n", FILENAME);
printf(" */\n\n");
printf("#include <sys/types.h>\n");
printf("#include <machine/vidc.h>\n\n");
printf("const char *monitor = \"%s\";\n", monitor);
printf("const int dpms = %d;\n", dpms);
printf("\n");
# Now define the modes array
printf("struct vidc_mode vidcmodes[] = {\n");
# Loop round all the modespecs on the command line
for (res = 2; res < realargc; res = res + 1) {
pos = -1;
found = -1;
closest = 200;
# Report the mode specifier being processed
printf("%s ==> ", ARGV[res]) > "/dev/stderr";
# Pull apart the modespec
args = split(ARGV[res], modespec, ",");
# We need at least 2 arguments
if (args < 2) {
printf("Invalid mode specifier\n") > "/dev/stderr";
continue;
}
# If we only have x,y default c and f
if (args == 2) {
modespec[3] = 256;
modespec[4] = -1;
}
# If we have x,y,f default c and re-arrange.
if (args == 3) {
modespec[4] = modespec[3];
modespec[3] = 256;
}
# Report the full mode specifier
printf("%d x %d x %d x %d : ", modespec[1], modespec[2],
modespec[3], modespec[4]) > "/dev/stderr";
# Now loop round all the modes we parsed and find the matches
for (loop = 0; loop < mode; loop = loop + 1) {
# Match X & Y
if (modespec[1] != modes[loop, 1]) continue;
if (modespec[2] != modes[loop, 2]) continue;
# Split the horizontal and vertical timings
# This is needed for the frame rate calculation
ht = split(modes[loop, 4], htimings, ",");
if (ht != 6) continue;
vt = split(modes[loop, 5], vtimings, ",");
if (vt != 6) continue;
# Calculate the frame rate
fr = modes[loop, 3] / (htimings[1] + htimings[2] + \
htimings[3] + htimings[4] + htimings[5] + \
htimings[6]) / ( vtimings[1] + vtimings[2] + \
vtimings[3] + vtimings[4] + vtimings[5] + \
vtimgings[6]);
fr = fr * 1000;
# Remember the frame rate
modes[loop, 7] = int(fr + 0.5);
# Report the frame rate
printf("%d ", modes[loop, 7]) > "/dev/stderr";
# Is this the closest
if (closest > mod(modes[loop, 7] - modespec[4])) {
closest = mod(modes[loop, 7] - modespec[4]);
pos = loop;
}
# Do we have an exact match ?
if (modes[loop, 7] == modespec[4])
found = pos;
}
# If no exact match use the nearest
if (found == -1)
found = pos;
# Did we find any sort of match ?
if (found == -1) {
printf("Cannot find mode") > "/dev/stderr";
continue;
}
# Report the frame rate matched
printf("- %d", modes[found, 7]) > "/dev/stderr";
# Output the mode as part of the mode definition array
printf("\t{ %6d, %22s, %22s, %d, %d, %d },\n",
modes[found, 3], modes[found, 4], modes[found, 5],
cdepth(modespec[3]), modes[found, 6], modes[found, 7]);
printf("\n") > "/dev/stderr";
}
# Add a terminating entry and close the array.
printf("\t{ 0 }\n");
printf("};\n");
}
#
# cdepth() function
#
# This returns the colour depth as a power of 2 + 1
#
function cdepth(depth) {
if (depth == 16)
return 5;
if (depth == 256)
return 9;
if (depth == 32768)
return 16;
if (depth == 65536)
return 17;
return 9;
}
#
# Simple mod() function
#
function mod(a) {
if (a < 0)
return -a;
return a;
}