# $NetBSD: makemodes.awk,v 1.7 2008/04/28 20:23:14 martin 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. # # 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 [ ...] # # where is # , # ,, # ,,, # # 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; # Translation of sync_pol to videomode.flags pol[0] = "HP|VP"; pol[1] = "HN|VP"; pol[2] = "HP|VN"; pol[3] = "HN|VN"; } # 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 \n"); printf("#include \n\n"); printf("const char * const monitor = \"%s\";\n", monitor); printf("const int dpms = %d;\n", dpms); printf("#define HP VID_PHSYNC\n"); printf("#define HN VID_NHSYNC\n"); printf("#define VP VID_PVSYNC\n"); printf("#define VN VID_NVSYNC\n"); printf("\n"); # Now define the modes array printf("const struct videomode vidc_videomode_list[] = {\n"); nmodes = 0 # 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]) | "cat 1>&2"; # Pull apart the modespec args = split(ARGV[res], modespec, ","); # We need at least 2 arguments if (args < 2) { printf("Invalid mode specifier\n") | "cat 1>&2"; 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]) | "cat 1>&2"; # 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] + \ vtimings[6]); fr = fr * 1000; # Remember the frame rate modes[loop, 7] = int(fr + 0.5); # Create the internal version of the timings modes[loop, "timings"] = \ sprintf( \ "{ %d, %d,%d,%d,%d, %d,%d,%d,%d, %s, \"%s\" }",\ modes[loop, 3], htimings[4], \ htimings[4] + htimings[5] + htimings[6], \ htimings[4] + htimings[5] + htimings[6] + \ htimings[1], \ htimings[4] + htimings[5] + htimings[6] + \ htimings[1] + htimings[2] + htimings[3], \ vtimings[4], \ vtimings[4] + vtimings[5] + vtimings[6], \ vtimings[4] + vtimings[5] + vtimings[6] + \ vtimings[1], \ vtimings[4] + vtimings[5] + vtimings[6] + \ vtimings[1] + vtimings[2] + vtimings[3], \ pol[modes[loop, 6]], modes[loop, 0]); # Report the frame rate printf("%d ", modes[loop, 7]) | "cat 1>&2"; # 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") | "cat 1>&2"; continue; } # Report the frame rate matched printf("- %d", modes[found, 7]) | "cat 1>&2"; # Output the mode as part of the mode definition array printf("\t%s,\n", modes[found, "timings"]); printf("\n") | "cat 1>&2"; nmodes++; } # Close the array. printf("};\n\n"); printf("const int vidc_videomode_count = %d;\n", nmodes); } # # Simple mod() function # function mod(a) { if (a < 0) return -a; return a; }