From: uz Date: Thu, 18 Nov 2010 18:47:01 +0000 (+0000) Subject: Renamed grc to grc65 to avoid name conflicts with another software named grc. X-Git-Tag: V2.13.3~580 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=bb1d6d94a31304805c028b1a1f0847ca4d84a9d1;p=cc65 Renamed grc to grc65 to avoid name conflicts with another software named grc. git-svn-id: svn://svn.cc65.org/cc65/trunk@4875 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/doc/Makefile b/doc/Makefile index f09bd02d0..5534baadd 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -38,7 +38,7 @@ SGML = apple2.sgml \ dio.sgml \ funcref.sgml \ geos.sgml \ - grc.sgml \ + grc65.sgml \ index.sgml \ intro.sgml \ ld65.sgml \ diff --git a/doc/geos.sgml b/doc/geos.sgml index d58a8764f..1f1ed4ddc 100644 --- a/doc/geos.sgml +++ b/doc/geos.sgml @@ -103,10 +103,11 @@ needs cc65. I want to thank Uz for his cc65 package, Alexander Boyce for his excellent GEOS Programmer's Reference Guide and BSW for GEOS.

-GEOSLib is covered by the same license as cc65. You can find the whole text among documentation. -I would really appreciate if you would like to send me your comments, suggestions, questions, -changes, bug reports etc. I will also appreciate if you will just give me a sign that you are -using GEOSLib - not especially something big and important, mail me even if you are just playing +GEOSLib is covered by the same license as cc65. You can find the whole text +among documentation. I would really appreciate if you would like to send me +your comments, suggestions, questions, changes, bug reports etc. I will also +appreciate if you will just give me a sign that you are using GEOSLib - not +especially something big and important, mail me even if you are just playing with it.

You can send postcards with hellos to: @@ -123,11 +124,12 @@ This chapter describes some rules you ought to obey, and how to use GEOSLib. Usage

-Apart from this file, which merely describes only standard GEOS library functions, you should read - All in all, you just need to place @@ -135,10 +137,11 @@ All in all, you just need to place on top of your source.

-As a general rule read the sources of example programs and read the headers. These are the most -reliable sources of knowledge ;). You will also find there many C macros representing various -arguments passed to functions. Please use them. You will find your sources easier to understand, -and it will be easier to find bugs. +As a general rule read the sources of example programs and read the headers. +These are the most reliable sources of knowledge ;). You will also find there +many C macros representing various arguments passed to functions. Please use +them. You will find your sources easier to understand, and it will be easier +to find bugs.

All types used in GEOSLib are diff --git a/doc/grc.sgml b/doc/grc.sgml deleted file mode 100644 index ea992eed8..000000000 --- a/doc/grc.sgml +++ /dev/null @@ -1,388 +0,0 @@ - -

- - - -grc -- GEOS Resource Compiler -<author><url name="Maciej 'YTM/Elysium' Witkowiak" url="mailto:ytm@elysium.pl"> -<and><url name="Greg King" url="mailto:gngking@erols.com"> -<date>VII 2000; VI,VII 2002; 2005-8-3 -<abstract> -This document describes a compiler that can create GEOS headers and menues for, -and VLIR files from, cc65-compiled programs. -</abstract> - -<!-- Table of contents --> -<toc> - -<!-- Begin the document --> - -<sect>Overview -<p><bf/grc/ is a part of cc65's GEOS support. The tool is necessary to -generate required and optional resources. A required resource for every GEOS -application is the header, that is: an icon, some strings, and some addresses. -Optional resources might be menu definitions, other headers (e.g., for data -files of an app.), dialog definitions, etc. Without an application's header, -GEOS is unable to load and start it. - -Currently, <bf/grc/ supports only menues and the required header definition, -along with support for building VLIR-structured files. - -<bf/grc/ generates output in three formats: C header, <bf/ca65/ source (.s), -and, for linking VLIR, <bf/ld65/ configuration script. That is because -application header data must be in assembly format, while menu definitions can -be translated easily into C. The purpose of the C file is to include it as a -header in only one project file. The assembly source should be processed by -<bf/ca65/, and linked as the first object (read about <ref -name="the building process" id="building-seq">). The VLIR structure currently -is supported for only projects that are written entirely in assembly code. - -<bf/grc/ can be used also as a handy VLIR linker -- used to build -VLIR-structured <tt/.cvt/ files out of prepared binary chains. - - - -<sect>Usage -<p>grc accepts the following options:<tscreen><verb> --f force the writing of the output files --o name name the .c output file --s name name the .s output file --l name name the ld65 output file --h show this help -</verb></tscreen> -When used as a VLIR linker, the correct syntax is:<tscreen><verb> - grc -vlir output.cvt header.bin vlir0.bin vlir1.bin ... -</verb></tscreen> -Default output names are made from input names with extensions replaced by -<tt/.h/ and <tt/.s/. <bf/grc/ will not overwrite existing files unless forced -to do so. That is done to avoid situations where you have <tt/test.c/ and -<tt/test.grc/ files. Both would put their output into <tt/test.s/. For that -reason, you should name your resource-files differently than sources, e.g., -<tt/resource.grc/ or <tt/apphead.grc/. - - - -<sect>Resource file format -<p>A resource file has the name extension <tt/.grc/. That is not required, but -it will make for an easier recognition of the file's purpose. Also, <bf/cl65/ -recognizes those files. <bf/grc/'s parser is very weak, at the moment; so, -read the comments carefully, and write resources exactly as they are written -here. Look out for CAPS. and small letters. Everything after a '<tt/;/', -until the end of the line, is considered as a comment, and ignored. See the -included <ref name="commented example .grc file" id="example-grc"> for a -better view of the problem. - - -<sect1>Menu definition -<p><tscreen><verb> -MENU menuName leftx,topy <ORIENTATION> { - "item name 1" <MENU_TYPE> pointer - ... - "item name x" <MENU_TYPE> pointer -}</verb></tscreen> -The definition starts with the keyword <tt/MENU/, then goes the menu's name, -which will be represented in C as <tt/const void/. Then are the co-ordinates -of the top left corner of the menu box. The position of the bottom right -corner is estimated, based on the length of item names and the menu's -orientation. It means that the menu box always will be as large as it should -be. Then, there's the orientation keyword; it can be either <tt/HORIZONTAL/ or -<tt/VERTICAL/. Between <tt/{/ and <tt/}/, there's the menu's -content. It consists of item definitions. First is an item name -- it has to -be in quotes. Next is a menu-type bit. It can be <tt/MENU_ACTION/ or -<tt/SUB_MENU/; either of them can be combined with the <tt/DYN_SUB_MENU/ bit -(see <url name="the GEOSLib documentation" url="geos.html"> for descriptions of -them). You can use C logical operators in expressions, but you have to do it -without spaces. So, a dynamically created submenu will be something like: -<tscreen><verb> -"dynamic" SUB_MENU|DYN_SUB_MENU create_dynamic</verb></tscreen> -The last part of the item definition is a pointer which can be any name that is -present in the C source code that includes the generated header. It can point -to a function or to another menu definition. - -If you are doing sub(sub)menu definitions, remember to place the lowest level -definition first, and the top-level menu as the last one. That way, the C -compiler won't complain about unknown names. - - -<sect1>Header definition -<p><tscreen><verb> -HEADER <GEOS_TYPE> "dosname" "classname" "version" { - author "Joe Schmoe" - info "This is my killer-app!" - date yy mm dd hh ss - dostype SEQ - mode any - structure SEQ -}</verb></tscreen> -The header definition describes the GEOS header sector which is unique to -each file. Currently, there's no way to change the default <bf/grc/ icon -(an empty frame). It will be possible in the next version. The definition -starts with the keyword <tt/HEADER/, then goes the GEOS file-type. You can use -only <tt/APPLICATION/ here at the moment. Then, there are (each one in quotes) -the DOS file-name (up to 16 characters), the GEOS Class name (up to 12 -characters), and the version info (up to 4 characters). The version should be -written as &dquot;<tt/V/x.y&dquot;, where <em/x/ is the major, and <em/y/ is -the minor, version number. Those fields, along with both braces, are required. -The lines between braces are optional, and will be replaced by default and -current values. The keyword <tt/author/ and its value in quotes name the -programmer, and can be up to 63 bytes long. <tt/info/ (in the same format) can -have up to 95 characters. If the <tt/date/ field is omitted, then the time of -that compilation will be placed into the header. Note that, if you do specify -the date, you have to write all 5 numbers. The <tt/dostype/ can be <tt/SEQ/, -<tt/PRG/, or <tt/USR/. <tt/USR/ is used by default; GEOS usually doesn't care. -The <tt/mode/ can be <tt/any/, <tt/40only/, <tt/80only/, or <tt/c64only/; and, -it describes system requirements. <tt/any/ will work on both 64-GEOS and -128-GEOS, in 40- and 80-column modes. <tt/40only/ will work on 128-GEOS in -40-column mode only. <tt/80only/ will work on only 128-GEOS in 80-column mode, -and <tt/c64only/ will work on only 64-GEOS. The default value for -<tt/structure/ is <tt/SEQ/ (sequential). You can put <tt/VLIR/ there, too; but -then, you also have to put in a third type of resource -- a VLIR-table -description. - - -<sect1>VLIR table description -<p><tscreen><verb> -VLIR headname address { - vlir0 - blank - vlir2 - blank - vlir4 -}</verb></tscreen> -The first element is the keyword <tt/VLIR/, then goes the name for the header -binary file (read below), and the base address for all VLIR chains that are -different from 0. It can be either decimal (e.g., <tt/4096/) or hexadecimal -with a <tt/0x/ prefix (e.g., <tt/0x1000/). Then, between braces are the names -of VLIR chain binaries or the keyword <tt/blank/ which denotes empty chains. -In the example, chains #1 and #3 are missing. The names between braces are -the names of binaries that contain code for each VLIR part. They matter only -for the generated <bf/ld65/ configuration file, and will be the names of the -resulting binary files after linking. Each one will contain one VLIR chain; -and, they will have to be put together, in the correct order, into a VLIR -<tt/.cvt/ file, by <bf/grc/ in its VLIR linker mode. - -The <tt/headname/ will be the name for the binary file which will contain only -a GEOS <tt/.cvt/ header made out of compiling the <tt/.s/ header file that also -was generated by <bf/grc/. At the end of the resulting <bf/ld65/ config. file -(<tt/.cfg/), in comments, there will be information about what commands are -required for putting the stuff together. Read <ref name="this description" -id="building-vlir"> for details. - - - -<sect>Building a GEOS sequential application<label id="building-seq"> -<p>Before proceeding, please read the <url name="compiler" url="cc65.html">, -<url name="assembler" url="ca65.html">, and <url name="linker" url="ld65.html"> -documentation, and find the appropriate sections about building programs, in -general. - -GEOS support in cc65 is based on the <em/Convert v2.5/ format, well-known in -the GEOS world. It means that each file built with the cc65 package has to be -deconverted, in GEOS, before it can be run. You can read a step-by-step -description of that in the GEOS section of the <url name="cc65 Compiler Intro" -url="intro.html">. - -Each project consists of four parts, two are provided by cc65. Those parts -are:<enum> -<item>application header -<item>start-up object -<item>application objects -<item>system library -</enum> -<bf/2./ and <bf/4./ are with cc65; you have to write the application, -yourself. ;-) - -The application header is defined in the <tt/HEADER/ section of the <tt/.grc/ -file, and processed into an assembly <tt/.s/ file. You must assemble it, with -<bf/ca65/, into the object <tt/.o/ format. - - -<sect1>Building a GEOS application without cl65 -<p>Assume that there are three input files: &dquot;<tt/test.c/&dquot; (a C -source), &dquot;<tt/test.h/&dquot; (a header file), and -&dquot;<tt/resource.grc/&dquot; (with menu and header definitions). Note the -fact that I <em/don't recommend/ naming that file &dquot;<tt/test.grc/&dquot;, -because you will have to be very careful with names (<bf/grc/ will make -&dquot;<tt/test.s/&dquot; and &dquot;<tt/test.h/&dquot; out of -&dquot;<tt/test.grc/&dquot;, by default; and, you don't want that because -&dquot;<tt/test.s/&dquot; is compiled from &dquot;<tt/test.c/&dquot;, and -&dquot;<tt/test.h/&dquot; is something completely different)! - -<bf/One important thing/ -- the top of &dquot;<tt/test.c/&dquot; looks like: -<tscreen><verb> -#include <geos.h> -#include "resource.h" -</verb></tscreen> -There are no other includes. - -<sect2>First step -- compiling the resources -<p><verb> -$ grc resource.grc -</verb> -will produce two output files: &dquot;<tt/resource.h/&dquot; and -&dquot;<tt/resource.s/&dquot;. - -Note that &dquot;<tt/resource.h/&dquot; is included at the top of -&dquot;<tt/test.c/&dquot;. So, resource compiling <em/must be/ the first step. - -<sect2>Second step -- assembling the application header -<p><verb> -$ ca65 -t geos resource.s -</verb> -And, voilá -- &dquot;<tt/resource.o/&dquot; is ready. - -<sect2>Third step -- compiling the code -<p><verb> -$ cc65 -t geos -O test.c -$ ca65 -t geos test.s -</verb> -That way, you have a &dquot;<tt/test.o/&dquot; object file which -contains all of the executable code. - -<sect2>Fourth and last step -- linking it together -<p><verb> -$ ld65 -t geos -o test.cvt resource.o geos.o test.o geos.lib -</verb> -&dquot;<tt/resource.o/&dquot; comes first because it contains the -header. The next one is &dquot;<tt/geos.o/&dquot;, a required starter-code -file; then, the actual application code in &dquot;<tt/test.o/&dquot;, and the -last is the GEOS system library. - -The resulting file &dquot;<tt/test.cvt/&dquot; is an executable that's -contained in the well-known GEOS <em/Convert/ format. Note that it's name -(<tt/test/) isn't important; the real name, after deconverting, is the DOS name -that was given in the header definition. - -At each step, a <tt/-t geos/ was present on the command-line. That switch is -required for the correct process of GEOS sequential app. building. - - - -<sect>Building a GEOS VLIR application<label id="building-vlir"> -<p>Currently, you can build VLIR applications only if your code is written in -assembly -- no C code allowed. - -In your sources, only the command <tt/.segment &dquot;/<em/NAME/<tt/&dquot;/ -will decide which code/data goes where. File-names don't matter. Segments -<tt/CODE/, <tt/RODATA/, <tt/DATA/, and <tt/BSS/ go into VLIR part #0. Segment -<tt/VLIR1/ goes into VLIR part #1, <tt/VLIR2/ goes into VLIR part #2, and so -on. - -The GEOS resource file's contents are similar to <ref -name="the sequential-file example" id="building-seq">, but there also is a -<tt/VLIR/ section and a <tt/structure VLIR/ tag. Here is that part:<tscreen> -<verb> -VLIR vlir-head.bin 0x3000 { - vlir-0.bin ; CODE, RODATA, DATA, BSS - vlir-1.bin ; VLIR1 - vlir-2.bin ; VLIR2 -}</verb></tscreen> -(Source files are only <tt/.s/.) - -OK, we have &dquot;<tt/cvthead.grc/&dquot;, so let's allow <bf/grc/ to compile -it:<verb> -$ grc cvthead.grc -</verb> -Now, there are two new files: &dquot;<tt/cvthead.cfg/&dquot; and -&dquot;<tt/cvthead.s/&dquot; -- the first one is a config. file for <bf/ld65/, -and the second one contains the GEOS <tt/.cvt/ header. It can be assembled: -<verb> -$ ca65 -t geos cvthead.s -</verb> -Now, we have &dquot;<tt/cvthead.o/&dquot;. The rest of the assembly -sources can be assembled:<verb> -$ ca65 -t geos vlir0.s -$ ca65 -t geos vlir1.s -$ ca65 -t geos vlir2.s -</verb> -Note that the file-names here, although similar to those from the -<tt/VLIR/ section of the <tt/.grc/ file, are not significant. The only thing -that matters is which code will go into which segment. - -Now, we can generate binaries. This time, the order of the arguments on the -command-line is not important.<verb> -$ ld65 -C cvthead.cfg vlir1.o cvthead.o vlir0.o vlir2.o -</verb> -As defined in the <tt/.grc/ file, we now have the binary parts of the -VLIR file: &dquot;<tt/vlir-head.bin/&dquot;, &dquot;<tt/vlir-0.bin/&dquot;, -&dquot;<tt/vlir-1.bin/&dquot;, and &dquot;<tt/vlir-2.bin/&dquot;. - -The last step is to put them together in the right order -- the order of the -arguments <em/is important/ this time! As suggested in the comments at the end -of &dquot;<tt/cvthead.cfg/&dquot;, we do:<verb> -$ grc -vlir output.cvt vlir-head.bin vlir-0.bin vlir-1.bin vlir-2.bin -</verb> -That is the end. The file &dquot;<tt/output.cvt/&dquot; can be -deconverted under GEOS. Note that <tt/-C cvthead.cfg/ was used on the -<bf/ld65/ command-line instead of the switch <tt/-t geos/. - - - -<sect>Bugs and feedback -<p>This is the first release of <bf/grc/, and it contains bugs, for sure! I am -aware of them; I know that the parser is weak, and if you don't follow the -grammar rules strictly, then everything will crash. However, if you find an -interesting bug, mail me. :-) Mail me also for help with writing your -<tt/.grc/ file correctly if you have problems with it. I would appreciate -comments also, and help on this file because I am sure that it can be written -better. - - - -<sect>Legal stuff -<p><bf/grc/ is covered by the same license as the whole cc65 package, so you -should see its documentation for more info. Anyway, if you like it, and want -to encourage me to work more on it, send me a postcard with a sight of your -neighbourhood, city, region, etc. Or, just e-mail me with info that you -actually used it. See <url name="the GEOSLib documentation" url="geos.html"> -for addresses. - - - -<appendix> -<sect>Appendix A -- example.grc<label id="example-grc"> -<p><tscreen><verb> -; Note that MENU can define both menues and submenues. -; If you want to use any C operators (such as "|", "&", etc.), do it WITHOUT -; any spaces between the arguments (the parser is simple and weak). - -MENU subMenu1 15,0 VERTICAL -; This is a vertical menu, placed at (15,0). -{ -; There are three items, all of them will call functions. -; The first and third ones are normal functions, see GEOSLib documentation for -; information about what the second function should return (it's a dynamic one). - "subitem1" MENU_ACTION smenu1 - "subitem2" MENU_ACTION|DYN_SUB_MENU smenu2 - "subitem3" MENU_ACTION smenu3 -} - -;; Format: MENU "name" left,top ALIGN { "itemname" TYPE pointer ... } - -MENU mainMenu 0,0 HORIZONTAL -; Here, we have our main menu, placed at (0,0), and it is a horizontal menu. -; Because it is a top-level menu, you would register it in your C source by -; using: DoMenu(&ero;mainMenu); -{ -; There are two items -- a submenu and an action. -; This calls a submenu named subMenu1 (see previous definition). - "first sub-menu" SUB_MENU subMenu1 -; This will work the same as an EnterDeskTop() call in C source code. - "quit" MENU_ACTION EnterDeskTop -} - -;; Format: HEADER <GEOS_TYPE> "dosname" "classname" "version" - -HEADER APPLICATION "MyFirstApp" "Class Name" "V1.0" -; This is a header for an APPLICATION which will be seen in the directory as a -; file named MyFirstApp with the Class-string "Class Name V1.0" -{ -; Not all fields are required, default and current values will be used. - author "Maciej Witkowiak" ; always in quotes! - info "Information text" ; always in quotes! -; date yy mm dd hh ss ; always 5 fields! -; dostype seq ; can be: PRG, SEQ, USR (only all UPPER- or lower-case) -; structure seq ; can be: SEQ, VLIR (only UPPER- or lower-case) - mode c64only ; can be: any, 40only, 80only, c64only -}</verb></tscreen> -</article> diff --git a/doc/grc65.sgml b/doc/grc65.sgml new file mode 100644 index 000000000..05afdbf8b --- /dev/null +++ b/doc/grc65.sgml @@ -0,0 +1,388 @@ +<!doctype linuxdoc system> +<article> + +<!-- Title information --> + +<title>grc65 -- GEOS Resource Compiler +<author><url name="Maciej 'YTM/Elysium' Witkowiak" url="mailto:ytm@elysium.pl"> +<and><url name="Greg King" url="mailto:gngking@erols.com"> +<date>VII 2000; VI,VII 2002; 2005-8-3 +<abstract> +This document describes a compiler that can create GEOS headers and menues for, +and VLIR files from, cc65-compiled programs. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview +<p><bf/grc65/ is a part of cc65's GEOS support. The tool is necessary to +generate required and optional resources. A required resource for every GEOS +application is the header, that is: an icon, some strings, and some addresses. +Optional resources might be menu definitions, other headers (e.g., for data +files of an app.), dialog definitions, etc. Without an application's header, +GEOS is unable to load and start it. + +Currently, <bf/grc65/ supports only menues and the required header definition, +along with support for building VLIR-structured files. + +<bf/grc65/ generates output in three formats: C header, <bf/ca65/ source (.s), +and, for linking VLIR, <bf/ld65/ configuration script. That is because +application header data must be in assembly format, while menu definitions can +be translated easily into C. The purpose of the C file is to include it as a +header in only one project file. The assembly source should be processed by +<bf/ca65/, and linked as the first object (read about <ref name="the building +process" id="building-seq">). The VLIR structure currently is supported for +only projects that are written entirely in assembly code. + +<bf/grc65/ can be used also as a handy VLIR linker -- used to build +VLIR-structured <tt/.cvt/ files out of prepared binary chains. + + + +<sect>Usage +<p>grc65 accepts the following options:<tscreen><verb> +-f force the writing of the output files +-o name name the .c output file +-s name name the .s output file +-l name name the ld65 output file +-h show this help +</verb></tscreen> +When used as a VLIR linker, the correct syntax is:<tscreen><verb> + grc65 -vlir output.cvt header.bin vlir0.bin vlir1.bin ... +</verb></tscreen> +Default output names are made from input names with extensions replaced by +<tt/.h/ and <tt/.s/. <bf/grc65/ will not overwrite existing files unless forced +to do so. That is done to avoid situations where you have <tt/test.c/ and +<tt/test.grc/ files. Both would put their output into <tt/test.s/. For that +reason, you should name your resource-files differently than sources, e.g., +<tt/resource.grc/ or <tt/apphead.grc/. + + + +<sect>Resource file format +<p>A resource file has the name extension <tt/.grc/. That is not required, but +it will make for an easier recognition of the file's purpose. Also, <bf/cl65/ +recognizes those files. <bf/grc65/'s parser is very weak, at the moment; so, +read the comments carefully, and write resources exactly as they are written +here. Look out for CAPS. and small letters. Everything after a '<tt/;/', +until the end of the line, is considered as a comment, and ignored. See the +included <ref name="commented example .grc file" id="example-grc"> for a +better view of the problem. + + +<sect1>Menu definition +<p><tscreen><verb> +MENU menuName leftx,topy <ORIENTATION> { + "item name 1" <MENU_TYPE> pointer + ... + "item name x" <MENU_TYPE> pointer +}</verb></tscreen> +The definition starts with the keyword <tt/MENU/, then goes the menu's name, +which will be represented in C as <tt/const void/. Then are the co-ordinates +of the top left corner of the menu box. The position of the bottom right +corner is estimated, based on the length of item names and the menu's +orientation. It means that the menu box always will be as large as it should +be. Then, there's the orientation keyword; it can be either <tt/HORIZONTAL/ or +<tt/VERTICAL/. Between <tt/{/ and <tt/}/, there's the menu's +content. It consists of item definitions. First is an item name -- it has to +be in quotes. Next is a menu-type bit. It can be <tt/MENU_ACTION/ or +<tt/SUB_MENU/; either of them can be combined with the <tt/DYN_SUB_MENU/ bit +(see <url name="the GEOSLib documentation" url="geos.html"> for descriptions of +them). You can use C logical operators in expressions, but you have to do it +without spaces. So, a dynamically created submenu will be something like: +<tscreen><verb> +"dynamic" SUB_MENU|DYN_SUB_MENU create_dynamic</verb></tscreen> +The last part of the item definition is a pointer which can be any name that is +present in the C source code that includes the generated header. It can point +to a function or to another menu definition. + +If you are doing sub(sub)menu definitions, remember to place the lowest level +definition first, and the top-level menu as the last one. That way, the C +compiler won't complain about unknown names. + + +<sect1>Header definition +<p><tscreen><verb> +HEADER <GEOS_TYPE> "dosname" "classname" "version" { + author "Joe Schmoe" + info "This is my killer-app!" + date yy mm dd hh ss + dostype SEQ + mode any + structure SEQ +}</verb></tscreen> +The header definition describes the GEOS header sector which is unique to +each file. Currently, there's no way to change the default <bf/grc65/ icon +(an empty frame). It will be possible in the next version. The definition +starts with the keyword <tt/HEADER/, then goes the GEOS file-type. You can use +only <tt/APPLICATION/ here at the moment. Then, there are (each one in quotes) +the DOS file-name (up to 16 characters), the GEOS Class name (up to 12 +characters), and the version info (up to 4 characters). The version should be +written as &dquot;<tt/V/x.y&dquot;, where <em/x/ is the major, and <em/y/ is +the minor, version number. Those fields, along with both braces, are required. +The lines between braces are optional, and will be replaced by default and +current values. The keyword <tt/author/ and its value in quotes name the +programmer, and can be up to 63 bytes long. <tt/info/ (in the same format) can +have up to 95 characters. If the <tt/date/ field is omitted, then the time of +that compilation will be placed into the header. Note that, if you do specify +the date, you have to write all 5 numbers. The <tt/dostype/ can be <tt/SEQ/, +<tt/PRG/, or <tt/USR/. <tt/USR/ is used by default; GEOS usually doesn't care. +The <tt/mode/ can be <tt/any/, <tt/40only/, <tt/80only/, or <tt/c64only/; and, +it describes system requirements. <tt/any/ will work on both 64-GEOS and +128-GEOS, in 40- and 80-column modes. <tt/40only/ will work on 128-GEOS in +40-column mode only. <tt/80only/ will work on only 128-GEOS in 80-column mode, +and <tt/c64only/ will work on only 64-GEOS. The default value for +<tt/structure/ is <tt/SEQ/ (sequential). You can put <tt/VLIR/ there, too; but +then, you also have to put in a third type of resource -- a VLIR-table +description. + + +<sect1>VLIR table description +<p><tscreen><verb> +VLIR headname address { + vlir0 + blank + vlir2 + blank + vlir4 +}</verb></tscreen> +The first element is the keyword <tt/VLIR/, then goes the name for the header +binary file (read below), and the base address for all VLIR chains that are +different from 0. It can be either decimal (e.g., <tt/4096/) or hexadecimal +with a <tt/0x/ prefix (e.g., <tt/0x1000/). Then, between braces are the names +of VLIR chain binaries or the keyword <tt/blank/ which denotes empty chains. +In the example, chains #1 and #3 are missing. The names between braces are +the names of binaries that contain code for each VLIR part. They matter only +for the generated <bf/ld65/ configuration file, and will be the names of the +resulting binary files after linking. Each one will contain one VLIR chain; +and, they will have to be put together, in the correct order, into a VLIR +<tt/.cvt/ file, by <bf/grc65/ in its VLIR linker mode. + +The <tt/headname/ will be the name for the binary file which will contain only +a GEOS <tt/.cvt/ header made out of compiling the <tt/.s/ header file that also +was generated by <bf/grc65/. At the end of the resulting <bf/ld65/ config. file +(<tt/.cfg/), in comments, there will be information about what commands are +required for putting the stuff together. Read <ref name="this description" +id="building-vlir"> for details. + + + +<sect>Building a GEOS sequential application<label id="building-seq"> +<p>Before proceeding, please read the <url name="compiler" url="cc65.html">, +<url name="assembler" url="ca65.html">, and <url name="linker" url="ld65.html"> +documentation, and find the appropriate sections about building programs, in +general. + +GEOS support in cc65 is based on the <em/Convert v2.5/ format, well-known in +the GEOS world. It means that each file built with the cc65 package has to be +deconverted, in GEOS, before it can be run. You can read a step-by-step +description of that in the GEOS section of the <url name="cc65 Compiler Intro" +url="intro.html">. + +Each project consists of four parts, two are provided by cc65. Those parts +are:<enum> +<item>application header +<item>start-up object +<item>application objects +<item>system library +</enum> +<bf/2./ and <bf/4./ are with cc65; you have to write the application, +yourself. ;-) + +The application header is defined in the <tt/HEADER/ section of the <tt/.grc/ +file, and processed into an assembly <tt/.s/ file. You must assemble it, with +<bf/ca65/, into the object <tt/.o/ format. + + +<sect1>Building a GEOS application without cl65 +<p>Assume that there are three input files: &dquot;<tt/test.c/&dquot; (a C +source), &dquot;<tt/test.h/&dquot; (a header file), and +&dquot;<tt/resource.grc/&dquot; (with menu and header definitions). Note the +fact that I <em/don't recommend/ naming that file &dquot;<tt/test.grc/&dquot;, +because you will have to be very careful with names (<bf/grc65/ will make +&dquot;<tt/test.s/&dquot; and &dquot;<tt/test.h/&dquot; out of +&dquot;<tt/test.grc/&dquot;, by default; and, you don't want that because +&dquot;<tt/test.s/&dquot; is compiled from &dquot;<tt/test.c/&dquot;, and +&dquot;<tt/test.h/&dquot; is something completely different)! + +<bf/One important thing/ -- the top of &dquot;<tt/test.c/&dquot; looks like: +<tscreen><verb> +#include <geos.h> +#include "resource.h" +</verb></tscreen> +There are no other includes. + +<sect2>First step -- compiling the resources +<p><verb> +$ grc65 resource.grc +</verb> +will produce two output files: &dquot;<tt/resource.h/&dquot; and +&dquot;<tt/resource.s/&dquot;. + +Note that &dquot;<tt/resource.h/&dquot; is included at the top of +&dquot;<tt/test.c/&dquot;. So, resource compiling <em/must be/ the first step. + +<sect2>Second step -- assembling the application header +<p><verb> +$ ca65 -t geos resource.s +</verb> +And, voilá -- &dquot;<tt/resource.o/&dquot; is ready. + +<sect2>Third step -- compiling the code +<p><verb> +$ cc65 -t geos -O test.c +$ ca65 -t geos test.s +</verb> +That way, you have a &dquot;<tt/test.o/&dquot; object file which +contains all of the executable code. + +<sect2>Fourth and last step -- linking it together +<p><verb> +$ ld65 -t geos -o test.cvt resource.o geos.o test.o geos.lib +</verb> +&dquot;<tt/resource.o/&dquot; comes first because it contains the +header. The next one is &dquot;<tt/geos.o/&dquot;, a required starter-code +file; then, the actual application code in &dquot;<tt/test.o/&dquot;, and the +last is the GEOS system library. + +The resulting file &dquot;<tt/test.cvt/&dquot; is an executable that's +contained in the well-known GEOS <em/Convert/ format. Note that it's name +(<tt/test/) isn't important; the real name, after deconverting, is the DOS name +that was given in the header definition. + +At each step, a <tt/-t geos/ was present on the command-line. That switch is +required for the correct process of GEOS sequential app. building. + + + +<sect>Building a GEOS VLIR application<label id="building-vlir"> +<p>Currently, you can build VLIR applications only if your code is written in +assembly -- no C code allowed. + +In your sources, only the command <tt/.segment &dquot;/<em/NAME/<tt/&dquot;/ +will decide which code/data goes where. File-names don't matter. Segments +<tt/CODE/, <tt/RODATA/, <tt/DATA/, and <tt/BSS/ go into VLIR part #0. Segment +<tt/VLIR1/ goes into VLIR part #1, <tt/VLIR2/ goes into VLIR part #2, and so +on. + +The GEOS resource file's contents are similar to <ref +name="the sequential-file example" id="building-seq">, but there also is a +<tt/VLIR/ section and a <tt/structure VLIR/ tag. Here is that part:<tscreen> +<verb> +VLIR vlir-head.bin 0x3000 { + vlir-0.bin ; CODE, RODATA, DATA, BSS + vlir-1.bin ; VLIR1 + vlir-2.bin ; VLIR2 +}</verb></tscreen> +(Source files are only <tt/.s/.) + +OK, we have &dquot;<tt/cvthead.grc/&dquot;, so let's allow <bf/grc65/ to compile +it:<verb> +$ grc65 cvthead.grc +</verb> +Now, there are two new files: &dquot;<tt/cvthead.cfg/&dquot; and +&dquot;<tt/cvthead.s/&dquot; -- the first one is a config. file for <bf/ld65/, +and the second one contains the GEOS <tt/.cvt/ header. It can be assembled: +<verb> +$ ca65 -t geos cvthead.s +</verb> +Now, we have &dquot;<tt/cvthead.o/&dquot;. The rest of the assembly +sources can be assembled:<verb> +$ ca65 -t geos vlir0.s +$ ca65 -t geos vlir1.s +$ ca65 -t geos vlir2.s +</verb> +Note that the file-names here, although similar to those from the +<tt/VLIR/ section of the <tt/.grc/ file, are not significant. The only thing +that matters is which code will go into which segment. + +Now, we can generate binaries. This time, the order of the arguments on the +command-line is not important.<verb> +$ ld65 -C cvthead.cfg vlir1.o cvthead.o vlir0.o vlir2.o +</verb> +As defined in the <tt/.grc/ file, we now have the binary parts of the +VLIR file: &dquot;<tt/vlir-head.bin/&dquot;, &dquot;<tt/vlir-0.bin/&dquot;, +&dquot;<tt/vlir-1.bin/&dquot;, and &dquot;<tt/vlir-2.bin/&dquot;. + +The last step is to put them together in the right order -- the order of the +arguments <em/is important/ this time! As suggested in the comments at the end +of &dquot;<tt/cvthead.cfg/&dquot;, we do:<verb> +$ grc65 -vlir output.cvt vlir-head.bin vlir-0.bin vlir-1.bin vlir-2.bin +</verb> +That is the end. The file &dquot;<tt/output.cvt/&dquot; can be +deconverted under GEOS. Note that <tt/-C cvthead.cfg/ was used on the +<bf/ld65/ command-line instead of the switch <tt/-t geos/. + + + +<sect>Bugs and feedback +<p>This is the first release of <bf/grc65/, and it contains bugs, for sure! I +am aware of them; I know that the parser is weak, and if you don't follow the +grammar rules strictly, then everything will crash. However, if you find an +interesting bug, mail me. :-) Mail me also for help with writing your +<tt/.grc/ file correctly if you have problems with it. I would appreciate +comments also, and help on this file because I am sure that it can be written +better. + + + +<sect>Legal stuff +<p><bf/grc65/ is covered by the same license as the whole cc65 package, so you +should see its documentation for more info. Anyway, if you like it, and want +to encourage me to work more on it, send me a postcard with a sight of your +neighbourhood, city, region, etc. Or, just e-mail me with info that you +actually used it. See <url name="the GEOSLib documentation" url="geos.html"> +for addresses. + + + +<appendix> +<sect>Appendix A -- example.grc<label id="example-grc"> +<p><tscreen><verb> +; Note that MENU can define both menues and submenues. +; If you want to use any C operators (such as "|", "&", etc.), do it WITHOUT +; any spaces between the arguments (the parser is simple and weak). + +MENU subMenu1 15,0 VERTICAL +; This is a vertical menu, placed at (15,0). +{ +; There are three items, all of them will call functions. +; The first and third ones are normal functions, see GEOSLib documentation for +; information about what the second function should return (it's a dynamic one). + "subitem1" MENU_ACTION smenu1 + "subitem2" MENU_ACTION|DYN_SUB_MENU smenu2 + "subitem3" MENU_ACTION smenu3 +} + +;; Format: MENU "name" left,top ALIGN { "itemname" TYPE pointer ... } + +MENU mainMenu 0,0 HORIZONTAL +; Here, we have our main menu, placed at (0,0), and it is a horizontal menu. +; Because it is a top-level menu, you would register it in your C source by +; using: DoMenu(&ero;mainMenu); +{ +; There are two items -- a submenu and an action. +; This calls a submenu named subMenu1 (see previous definition). + "first sub-menu" SUB_MENU subMenu1 +; This will work the same as an EnterDeskTop() call in C source code. + "quit" MENU_ACTION EnterDeskTop +} + +;; Format: HEADER <GEOS_TYPE> "dosname" "classname" "version" + +HEADER APPLICATION "MyFirstApp" "Class Name" "V1.0" +; This is a header for an APPLICATION which will be seen in the directory as a +; file named MyFirstApp with the Class-string "Class Name V1.0" +{ +; Not all fields are required, default and current values will be used. + author "Maciej Witkowiak" ; always in quotes! + info "Information text" ; always in quotes! +; date yy mm dd hh ss ; always 5 fields! +; dostype seq ; can be: PRG, SEQ, USR (only all UPPER- or lower-case) +; structure seq ; can be: SEQ, VLIR (only UPPER- or lower-case) + mode c64only ; can be: any, 40only, 80only, c64only +}</verb></tscreen> +</article> diff --git a/doc/index.sgml b/doc/index.sgml index f9fa2a62a..0d84a367c 100644 --- a/doc/index.sgml +++ b/doc/index.sgml @@ -34,8 +34,8 @@ Main documentation page, contains links to other available stuff. <tag><htmlurl url="da65.html" name="da65.html"></tag> Describes the da65 6502/65C02 disassembler. - <tag><htmlurl url="grc.html" name="grc.html"></tag> - Describes the GEOS resource compiler (grc). + <tag><htmlurl url="grc65.html" name="grc65.html"></tag> + Describes the GEOS resource compiler (grc65). <tag><htmlurl url="ld65.html" name="ld65.html"></tag> Describes the ld65 linker. diff --git a/packages/debian/cc65.manpages b/packages/debian/cc65.manpages index 43e9638da..05a9a99aa 100644 --- a/packages/debian/cc65.manpages +++ b/packages/debian/cc65.manpages @@ -4,6 +4,6 @@ debian/ca65html.1 debian/cc65.1 debian/cl65.1 debian/da65.1 -debian/grc.1 +debian/grc65.1 debian/ld65.1 debian/od65.1 diff --git a/packages/debian/grc.1 b/packages/debian/grc.1 deleted file mode 100644 index 0fa03ebb2..000000000 --- a/packages/debian/grc.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/cc65.1 diff --git a/packages/debian/grc65.1 b/packages/debian/grc65.1 new file mode 100644 index 000000000..0fa03ebb2 --- /dev/null +++ b/packages/debian/grc65.1 @@ -0,0 +1 @@ +.so man1/cc65.1 diff --git a/packages/debian/rules b/packages/debian/rules index 826c0c58f..36b284aab 100644 --- a/packages/debian/rules +++ b/packages/debian/rules @@ -62,7 +62,7 @@ binary-arch: checkroot build dh_testroot -a dh_installdirs -a dh_installmenu -a - for bin in ar65 ca65 cc65 cl65 da65 grc ld65 od65 ca65html; do \ + for bin in ar65 ca65 cc65 cl65 da65 grc65 ld65 od65 ca65html; do \ install -m0755 `pwd`/src/$$bin/$$bin debian/cc65/usr/bin; \ done for info in ar65 ca65 cc65 cl65 ld65 debugging dio geos coding intro library; do \ diff --git a/packages/rpm/redhat/cc65.spec b/packages/rpm/redhat/cc65.spec index 5e2d300dd..944f7a6da 100644 --- a/packages/rpm/redhat/cc65.spec +++ b/packages/rpm/redhat/cc65.spec @@ -324,7 +324,7 @@ This package contains the header files and libraries needed to write GEOS programs for the C64/C128 using the cc65 crosscompiler. %files geos -%attr(755,root,root) /usr/bin/grc +%attr(755,root,root) /usr/bin/grc65 %attr(644,root,root) %{_libdir}/cc65/lib/geos.lib %attr(755,root,root) %dir %{_libdir}/cc65/include/geos %attr(644,root,root) %{_libdir}/cc65/include/geos/*.h @@ -492,7 +492,7 @@ install -s -m 755 src/cc65/cc65 $RPM_BUILD_ROOT%{_bindir} install -s -m 755 src/cl65/cl65 $RPM_BUILD_ROOT%{_bindir} install -s -m 755 src/co65/co65 $RPM_BUILD_ROOT%{_bindir} install -s -m 755 src/da65/da65 $RPM_BUILD_ROOT%{_bindir} -install -s -m 755 src/grc/grc $RPM_BUILD_ROOT%{_bindir} +install -s -m 755 src/grc65/grc65 $RPM_BUILD_ROOT%{_bindir} install -s -m 755 src/ld65/ld65 $RPM_BUILD_ROOT%{_bindir} install -s -m 755 src/od65/od65 $RPM_BUILD_ROOT%{_bindir} diff --git a/src/grc/grc.c b/src/grc/grc.c deleted file mode 100644 index efb8dc686..000000000 --- a/src/grc/grc.c +++ /dev/null @@ -1,738 +0,0 @@ - -/* - GEOS resource compiler - - by Maciej 'YTM/Elysium' Witkowiak - - see GEOSLib documentation for license info - -*/ - -/* - - make it work, then do it better - - more or less comments? it was hard to code, should be even harder to - understand =D - - add loadable icons feature (binary - 63 bytes) -*/ - -/* - err, maybe free allocated memory, huh? (who cares, it's just a little prog...) -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <time.h> - -#include "grc.h" - -/* common stuff */ -#include "fname.h" -#include "abend.h" -#include "chartype.h" -#include "xmalloc.h" - -void VLIRLinker(int argc, char *argv[]) { -FILE *outCVT, *input; -unsigned char *buffer; -unsigned char vlirtabt[127]; -unsigned char vlirtabs[127]; -int i,j,lastarg; -unsigned l; -int bytes; -int blocks,rest; - - i=2; - - /* check if we know enough */ - - if (argc<4) - AbEnd("too few arguments, required [out] [cvthead] [vlir0] ...\n"); - - /* first open and copy CVT header */ - - outCVT = fopen(argv[i],"wb+"); - if (outCVT==NULL) - AbEnd("can't open output:%s\n",strerror(errno)); - - ++i; - input = fopen(argv[i],"rb"); - if (input==NULL) - AbEnd("can't open input:%s\n",strerror(errno)); - - buffer = xmalloc(THIS_BUFFER_IS_SOOO_HUGE); - memset(buffer,0,THIS_BUFFER_IS_SOOO_HUGE); - - bytes = fread(buffer,1,1024,input); - fclose(input); - if (bytes!=508) - AbEnd("%s is not a cvt header\n",argv[i]); - - fwrite(buffer,1,bytes,outCVT); - - /* now put 254 bytes of VLIR table, to update later */ - - /* clear out things */ - memset(buffer,0,512); - fwrite(buffer,1,254,outCVT); - for (l=0;l<sizeof(vlirtabt)/sizeof(vlirtabt[0]);l++) { - vlirtabt[l]=0; - vlirtabs[l]=0; - } - - /* scan arguments for the last one that is not blank or nonexistant */ - j=argc; - lastarg=argc-1; - while (j!=3) { - --j; - if ((strcmp(argv[j],"blank")==0)||(strcmp(argv[j],"noexist")==0)) - --lastarg; - } - - /* now read all VLIR chains, align to 254 bytes */ - - ++i; - j=0; - while (i!=argc) { - if (strcmp(argv[i],"blank")==0) { - vlirtabt[j]=0; vlirtabs[j]=0; } - else if (strcmp(argv[i],"noexist")==0) { - vlirtabt[j]=0; vlirtabs[j]=0xff; } - else { - memset(buffer,0,bytes+512); - input = fopen(argv[i],"rb"); - if (input==NULL) - AbEnd("couldn't open %s:%s\n",argv[i],strerror(errno)); - bytes = fread(buffer,1,THIS_BUFFER_IS_SOOO_HUGE,input); - fclose(input); - if (bytes==0) - AbEnd("couldn't read %s:%s\n",argv[i],strerror(errno)); - blocks = bytes / 254; - rest = bytes % 254; - if (rest==0) { - rest = 255; - --blocks; - } else { - ++rest; - } - vlirtabt[j]=blocks+1; vlirtabs[j]=rest; - /* do not pad the last chain - it doesn't change or break anything - but filesize in bytes of .cvt will be identical to native cvt */ - if (i==lastarg) - fwrite(buffer,1,bytes,outCVT); - else - fwrite(buffer,1,(blocks+1)*254,outCVT); - } - ++j; - ++i; - } - - free(buffer); - - /* now rewind and update VLIR table */ - - fflush(outCVT); - fseek(outCVT,508,SEEK_SET); - for (l=0;l<sizeof(vlirtabt)/sizeof(vlirtabt[0]);l++) { - fputc(vlirtabt[l],outCVT); - fputc(vlirtabs[l],outCVT); - } - fclose(outCVT); - exit(EXIT_SUCCESS); -} - -void printCHeader (void) { - - fprintf(outputCFile, "\n/*\n\tThis file was generated by GEOS Resource Compiler\n" - "\n\tDO NOT EDIT! Any changes will be lost!\n" - "\n\tEdit proper resource file instead\n" - "\n*/\n\n"); -} - -void printSHeader (void) { - - fprintf(outputSFile, "\n;\n;\tThis file was generated by GEOS Resource Compiler\n;" - "\n;\tDO NOT EDIT! Any changes will be lost!\n;" - "\n;\tEdit proper resource file instead\n;" - "\n;\n\n"); -} - -void printVHeader (void) { - fprintf(outputVFile, "\n#\n#\tThis file was generated by GEOS Resource Compiler\n#" - "\n#\tDO NOT EDIT! Any changes will be lost!\n#" - "\n#\tEdit proper resource file instead\n#" - "\n#\tLook at end of this file to find commandline that must be used\n" - "#\tto invoke ld65 and grc (as VLIR linker)\n#" - "\n#\n\n"); -} - -void openCFile (void) { - if ((CFnum==0) && (forceFlag==0)) { - /* test if file exists already and no forcing*/ - if ((outputCFile = fopen (outputCName,"r"))!=0) - AbEnd("file %s already exists, aborting\n", outputCName); - } - if ((outputCFile = fopen (outputCName,outputCMode))==0) - AbEnd("can't open file %s for writing: %s\n",outputCName,strerror (errno)); - if (CFnum==0) { - outputCMode[0]='a'; - printCHeader(); - CFnum++; - } -} - -void openSFile (void) { - if ((SFnum==0) && (forceFlag==0)) { - /* test if file exists already and no forcing*/ - if ((outputSFile = fopen (outputSName,"r"))!=0) - AbEnd("file %s already exists, aborting\n", outputSName); - } - if ((outputSFile = fopen (outputSName,outputSMode))==0) - AbEnd("can't open file %s for writing: %s\n",outputSName,strerror (errno)); - if (SFnum==0) { - outputSMode[0]='a'; - printSHeader(); - SFnum++; - } -} - -void openVFile (void) { - if ((VFnum==0) && (forceFlag==0)) { - /* test if file exists already and no forcing*/ - if ((outputVFile = fopen (outputVName,"r"))!=0) - AbEnd("file %s already exists, aborting\n", outputVName); - } - if ((outputVFile = fopen (outputVName,outputVMode))==0) - AbEnd("can't open file %s for writting: %s\n",outputVName,strerror (errno)); - if (VFnum==0) { - outputVMode[0]='a'; - printVHeader(); - VFnum++; - } -} - -void printUsage (void) { - printf("Usage: %s [options] file\n" - "Options:\n" - "\t-h, -?\t\tthis help\n" - "\t-f\t\tforce writting files\n" - "\t-o name\t\tname C output file\n" - "\t-s name\t\tname asm output file\n" - "\t-l name\t\tname ld65 config output file (for vlir)\n" - "Or as VLIR linker: %s -vlir output.cvt header [vlir0] ... [blank] ... [vlir_n]\n", - ProgName,ProgName); -} - -int findToken (const char **tokenTbl, const char *token) { -/* takes as input table of tokens and token, returns position in table or -1 if not found */ -int a=0; - - while (strlen(tokenTbl[a])!=0) { - if (strcmp(tokenTbl[a],token)==0) break; - a++; - } - if (strlen(tokenTbl[a])==0) a=-1; - return a; -} - -char *nextPhrase() { - return strtok(NULL, "\""); - } - -char *nextWord() { - return strtok(NULL, " "); - } - -void setLen (char *name, unsigned len) { - if (strlen(name)>len) - name[len]='\0'; -} - -void fillOut (char *name, int len, char *filler) { -int a; - setLen (name, len); - fprintf(outputSFile, ".byte \"%s\"\n\t\t", name); - a = len - strlen(name); - if (a!=0) { - fprintf(outputSFile, ".byte %s", filler); - while (--a!=0) fprintf(outputSFile, ", %s", filler); - fprintf(outputSFile, "\n\t\t"); - } -} - -char *bintos(unsigned char a, char out[7]) { -int i=0; - for (;i<8;i++) { - out[7-i] = ((a & 1)==0) ? '0' : '1'; - a = a >> 1; }; - out[i]='\0'; -return out; -} - -int getNameSize (const char *word) { -/* count length of a word using BSW 9 font table */ -int a=0, i=0; - - while (word[i]!='\0') { - a+=(BSWTab[word[i]-31] - BSWTab[word[i]-32]); i++; } - - return a; -} - -void DoMenu (void) { - -int a, size, tmpsize, item=0; -char *token; -char namebuff[255]=""; -struct menu myMenu; -struct menuitem *curItem, *newItem; - - openCFile(); - - myMenu.name=nextWord(); - myMenu.left=atoi(nextWord()); - myMenu.top=atoi(nextWord()); - myMenu.type=nextWord(); - - if (strcmp(nextWord(),"{")!=0) { - AbEnd ("menu '%s' description has no opening bracket!\n", myMenu.name); - } - curItem = xmalloc(sizeof(struct menuitem)); - myMenu.item=curItem; - do { - token = nextWord(); - if (strcmp(token,"}")==0) break; - if (token[strlen(token)-1]!='"') { - strcpy (namebuff, token); - do { - token = nextWord(); - strcat (namebuff, " "); - strcat (namebuff, token); - } while (token[strlen(token)-1]!='"'); - token = xmalloc(strlen(namebuff)); - strcpy (token, namebuff); - } - curItem->name=token; - curItem->type=nextWord(); - curItem->target=nextWord(); - newItem=xmalloc(sizeof(struct menuitem)); - curItem->next=newItem; - curItem=newItem; - item++; - } while (strcmp(token,"}")!=0); - if (item==0) AbEnd ("menu '%s' has 0 items!\n", myMenu.name); - if (item>31) AbEnd ("menu '%s' has too many items!\n", myMenu.name); - - curItem->next=NULL; - - /* Count menu sizes */ - - size=0; - curItem=myMenu.item; - if (strstr(myMenu.type,"HORIZONTAL")!=NULL) { - /* menu is HORIZONTAL, ysize=15, sum xsize of all items +~8?*/ - myMenu.bot=myMenu.top+15; - for (a=0;a!=item;a++) { - size+=getNameSize(curItem->name); - curItem=curItem->next; - }; - } else { - /* menu is VERTICAL, ysize=item*15, count largest xsize of all items +~8? */ - myMenu.bot=myMenu.top+(14*item); - for (a=0;a!=item;a++) { - tmpsize=getNameSize(curItem->name); - size = (size > tmpsize) ? size : tmpsize; - curItem=curItem->next; - }; - }; - myMenu.right=myMenu.left+size-1; - - curItem=myMenu.item; - for (a=0;a!=item;a++) { - /* print prototype only if MENU_ACTION or DYN_SUB_MENU are present in type */ - if ((strstr(curItem->type, "MENU_ACTION")!=NULL) || (strstr(curItem->type, "DYN_SUB_MENU")!=NULL)) - fprintf(outputCFile, "void %s (void);\n", curItem->target); - curItem=curItem->next; - } - - fprintf(outputCFile, "\nconst void %s = {\n\t(char)%i, (char)%i,\n\t(int)%i, (int)%i,\n\t" - "(char)(%i | %s),\n", myMenu.name, myMenu.top, myMenu.bot, myMenu.left, - myMenu.right, item, myMenu.type); - - curItem=myMenu.item; - for (a=0;a!=item;a++) { - fprintf(outputCFile, "\t%s, (char)%s, (int)", curItem->name, curItem->type); - if ((strstr(curItem->type, "SUB_MENU")!=NULL) && (strstr(curItem->type, "DYN_SUB_MENU")==NULL)) - fprintf(outputCFile, "&"); - fprintf(outputCFile, "%s,\n", curItem->target); - curItem=curItem->next; - } - - fprintf(outputCFile, "\t};\n\n"); - - if (fclose (outputCFile)!=0) - AbEnd("error closing %s: %s\n",outputCName,strerror (errno)); -} - -void DoHeader (void) { - -time_t t; -struct tm *my_tm; - -struct appheader myHead; -char *token; -char i1[9], i2[9], i3[9]; -int a, b; - - openSFile(); - - token = nextWord(); - - a = findToken (hdrFTypes, token); - - switch (a) { - case 0: myHead.geostype = 6; break; - case 1: myHead.geostype = 14; break; - default: AbEnd("filetype '%s' is not supported yet\n", token); - } - - myHead.dosname = nextPhrase(); - nextPhrase(); - myHead.classname = nextPhrase(); - nextPhrase(); - myHead.version = nextPhrase(); - - /* put default values into myHead here */ - myHead.author = "cc65"; - myHead.info = "Program compiled with cc65 and GEOSLib."; - myHead.dostype = 128+3; - myHead.structure = 0; - myHead.mode = 0; - - t = time(NULL); - my_tm = localtime (&t); - - myHead.year = my_tm->tm_year; - myHead.month = my_tm->tm_mon+1; - myHead.day = my_tm->tm_mday; - myHead.hour = my_tm->tm_hour; - myHead.min = my_tm->tm_min; - - if (strcmp(nextWord(),"{")!=0) - AbEnd ("header '%s' has no opening bracket!\n", myHead.dosname); - - do { - token=nextWord(); - if (strcmp(token, "}")==0) break; - switch (a = findToken (hdrFields, token)) { - case -1: - AbEnd ("unknown field '%s' in header '%s'\n", token, myHead.dosname); - break; - case 0: /* author */ - myHead.author = nextPhrase(); break; - case 1: /* info */ - myHead.info = nextPhrase(); break; - case 2: /* date */ - myHead.year = atoi(nextWord()); - myHead.month = atoi(nextWord()); - myHead.day = atoi(nextWord()); - myHead.hour = atoi(nextWord()); - myHead.min = atoi(nextWord()); - break; - case 3: /* dostype */ - switch (b = findToken (hdrDOSTp, nextWord())) { - case -1: - AbEnd ("unknown dostype in header '%s'\n", myHead.dosname); - break; - default: - myHead.dostype = b/2 + 128 + 1; - break; - } - break; - case 4: /* mode */ - switch (b = findToken (hdrModes, nextWord())) { - case -1: - AbEnd ("unknown mode in header '%s'\n", myHead.dosname); - case 0: - myHead.mode = 0x40; break; - case 1: - myHead.mode = 0x00; break; - case 2: - myHead.mode = 0xc0; break; - case 3: - myHead.mode = 0x80; break; - } - break; - case 5: /* structure */ - switch (b = findToken(hdrStructTp, nextWord())) { - case -1: - AbEnd ("unknown structure type in header '%s'\n", myHead.dosname); - case 0: - case 1: - myHead.structure = 0; break; - case 2: - case 3: - myHead.structure = 1; break; - } - break; - } - - } while (strcmp(token, "}")!=0); - - /* OK, all information is gathered, do flushout */ - - fprintf(outputSFile, - "\t\t\t.segment \"HEADER\"\n\n\t\t.byte %i\n\t\t.word 0\n\t\t", myHead.dostype); - - fillOut(myHead.dosname,16,"$a0"); - - fprintf(outputSFile, - ".word 0\n\t\t.byte %i\n\t\t.byte %i\n\t\t.byte %i, %i, %i, %i, %i\n\n\t\t" - ".word 0\n\t\t.byte \"PRG formatted GEOS file V1.0\"\n\n\t\t.res $c4\n\n\t\t" - ".byte 3, 21, 63 | $80\n\t\t", - myHead.structure, myHead.geostype, myHead.year, myHead.month, myHead.day, - myHead.hour, myHead.min); - - for (a=0;a!=63;a=a+3) { - fprintf(outputSFile, - ".byte %%%s, %%%s, %%%s\n\t\t", - bintos(icon1[a], i1), bintos(icon1[a+1], i2), bintos(icon1[a+2], i3)); }; - - fprintf(outputSFile, - "\n\t\t.byte %i, %i, %i\n\t\t.word $0400, $0400-1, $0400\n\n\t\t", - myHead.dostype, myHead.geostype, myHead.structure); - - fillOut(myHead.classname,12,"$20"); - - fillOut(myHead.version,4,"0"); - - fprintf(outputSFile, - ".byte 0, 0, 0\n\t\t.byte %i\n\n\t\t", myHead.mode); - - setLen(myHead.author,62); - fprintf(outputSFile, - ".byte \"%s\"\n\t\t.byte 0\n\t\t.res (63-%i)\n\n\t\t", - myHead.author, (int) (strlen(myHead.author)+1)); - - setLen(myHead.info, 95); - fprintf(outputSFile, - ".byte \"%s\"\n\t\t.byte 0\n\t\t.res (96-%i)\n\n", - myHead.info, (int) (strlen(myHead.info)+1)); - - if (fclose (outputSFile)!=0) - AbEnd("error closing %s: %s\n",outputSName,strerror (errno)); - -} - -void DoVLIR (void) { - -char *token; -char *headname; -int i,numchains,vlirbase; -struct vlirentry { - char *chainname; - int exist; -}; - -struct vlirentry vlirtable[127]; - - openVFile(); - - headname = nextWord(); - - vlirbase = strtol(nextWord(),NULL,0); - - if (strcmp(nextWord(),"{")!=0) - AbEnd ("VLIR description has no opening bracket!\n"); - - numchains=0; - - do { - token=nextWord(); - if (strcmp(token, "}")==0) break; - numchains++; - if (numchains>127) { - AbEnd("Too many VLIR chains!\n"); - } - vlirtable[numchains].chainname=token; - - /* for first chain - name header */ - if (numchains==1) { - fprintf(outputVFile,"MEMORY {\n\tHEADER: start = $204, size = 508, file = \"%s\";\n" - "\tVLIR0: start = $0400, size = $5C00, file = \"%s\";\n",headname,token); - } else { - /* for all other - segment */ - /* ignore non-existing segments */ - vlirtable[numchains].exist=1; - if ( (strcmp(token,"blank")==0) || (strcmp(token,"noexist")==0) ) { - vlirtable[numchains].exist=0; - fprintf(outputVFile,"#"); - } - fprintf(outputVFile,"\tVLIR%i: start = $%x, size = $%x, file = \"%s\";\n", - numchains-1,vlirbase,0x5c00-vlirbase,token); - } - - } while (strcmp(token, "}")!=0); - fprintf(outputVFile,"}\n\n"); - - if (numchains==0) { - AbEnd("There must be at least one VLIR chain.\n"); - }; - - /* now put segments info */ - fprintf(outputVFile,"SEGMENTS {\n\tHEADER: load = HEADER, type = ro;\n" - "\tCODE: load = VLIR0, type = ro;\n" - "\tRODATA: load = VLIR0, type = ro;\n" - "\tDATA: load = VLIR0, type = rw;\n" - "\tBSS: load = VLIR0, type = bss, define = yes;\n\n"); - - for (i=2;i<=numchains;i++) { - if (vlirtable[i].exist==0) { - fprintf(outputVFile,"#"); - } - fprintf(outputVFile,"\tVLIR%i: load = VLIR%i, type = rw, define = yes;\n",i-1,i-1); - } - fprintf(outputVFile,"}\n"); - - /* now put usage info */ - fprintf(outputVFile,"\n# ld65 -o output.cvt -C %s file1.o file2.o ...",outputVName); - fprintf(outputVFile,"\n# grc -vlir outputname %s",headname); - for (i=1;i<=numchains;i++) { - fprintf(outputVFile," %s",vlirtable[i].chainname); - } - fprintf(outputVFile,"\n"); - - if (fclose (outputVFile)!=0) - AbEnd("error closing %s: %s\n",outputVName,strerror (errno)); -} - -char *filterInput (FILE *F, char *tbl) { -/* loads file into buffer filtering it out */ -int a, prevchar=-1, i=0, bracket=0, quote=1; - - while (1) { - a = getc(F); - if ((a=='\n')||(a=='\015')) a = ' '; - if (a==',' && quote) a = ' '; - if (a=='\042') quote=!quote; - if (quote) { - if ((a=='{')||(a=='(')) bracket++; - if ((a=='}')||(a==')')) bracket--; - } - if (a==EOF) { tbl[i]='\0'; xrealloc(tbl, i+1); break; }; - if (IsSpace(a)) { - if ((prevchar!=' ') && (prevchar!=-1)) { tbl[i++]=' '; prevchar=' '; } - } else { - if (a==';' && quote) { do { a = getc (F); } while (a!='\n'); fseek(F,-1,SEEK_CUR); } - else { - tbl[i++]=a; prevchar=a; } - } - } - - if (bracket!=0) AbEnd("there are unclosed brackets!\n"); - - return tbl; -} - -void processFile (const char *filename) { - -FILE *F; - -char *str; -char *token; - -int head=0; /* number of processed HEADER sections */ -int vlir=0; /* number of processed VLIR sections */ - - if ((F = fopen (filename,"r"))==0) - AbEnd("can't open file %s for reading: %s\n",filename,strerror (errno)); - - str=filterInput(F, xmalloc(BLOODY_BIG_BUFFER)); - - token = strtok (str," "); - - do { - if (str!=NULL) { - switch (findToken (mainToken, token)) { - - case 0: DoMenu(); break; - case 1: - if (++head!=1) { - AbEnd ("more than one HEADER section, aborting.\n"); - } else { - DoHeader(); - } - break; - case 2: break; /* icon not implemented yet */ - case 3: break; /* dialog not implemented yet */ - case 4: - if (++vlir!=1) { - AbEnd ("more than one VLIR section, aborting.\n"); - } else { - DoVLIR(); - } - break; - default: AbEnd ("unknown section %s.\n",token); break; - } - } - token = nextWord(); - } while (token!=NULL); -} - -int main(int argc, char *argv[]) { - -int ffile=0, i=1; - - ProgName = argv[0]; - while (i < argc) { - const char *arg = argv[i]; - if (arg[0] == '-') { - switch (arg[1]) { - case 'f': - forceFlag=1; - break; - case 'o': - outputCName=argv[++i]; - break; - case 's': - outputSName=argv[++i]; - break; - case 'l': - outputVName=argv[++i]; - break; - case 'h': - case '?': - printUsage(); - exit (EXIT_SUCCESS); - break; - case 'v': - if (strcmp(arg,"-vlir")==0) { - VLIRLinker(argc,argv); - exit (EXIT_SUCCESS); - break; - } else { - AbEnd("unknown option %s\n",arg); - break; - } - default: AbEnd("unknown option %s\n",arg); - } - } else { - ffile++; - - if (outputCName==NULL) - outputCName = MakeFilename(arg,".h"); - if (outputSName==NULL) - outputSName = MakeFilename(arg,".s"); - if (outputVName==NULL) - outputVName = MakeFilename(arg,".cfg"); - - processFile(arg); - - } - i++; - } - if (ffile==0) AbEnd("no input file\n"); - - return EXIT_SUCCESS; -} diff --git a/src/grc/grc.h b/src/grc/grc.h deleted file mode 100644 index 9825fe931..000000000 --- a/src/grc/grc.h +++ /dev/null @@ -1,77 +0,0 @@ - -/* I hope that no one will be able to create a .grc bigger than this... */ -#define BLOODY_BIG_BUFFER 65000 -/* there are no 6MB GEOS binaries... I hope! */ -#define THIS_BUFFER_IS_SOOO_HUGE 6000000 - -struct menuitem { - char *name; - char *type; - char *target; - struct menuitem *next; }; - -struct menu { - char *name; - int top, left; - int bot, right; - char *type; - struct menuitem *item; }; - -struct appheader { - int year,month,day,hour,min; - int mode; - int dostype; - int geostype; - int structure; - char *dosname; - char *classname; - char *version; - char *author; - char *info; }; - -const char *mainToken[] = { - "MENU", "HEADER", "ICON", "DIALOG", "VLIR", "" }; - -const char *hdrFTypes[] = { - "APPLICATION", "AUTO_EXEC", "DESK_ACC", "ASSEMBLY", "DISK_DEVICE", "PRINTER", "SYSTEM", "" }; - -const char *hdrFields[] = { - "author", "info", "date", "dostype", "mode", "structure", "" }; - -const char *hdrDOSTp[] = { - "seq", "SEQ", "prg", "PRG", "usr", "USR", "" }; - -const char *hdrStructTp[] = { - "seq", "SEQ", "vlir", "VLIR", "" }; - -const char *hdrModes[] = { - "any", "40only", "80only", "c64only", "" }; - -const int BSWTab[] = { 0, - 0x005, 0x007, 0x00b, 0x011, 0x017, - 0x01d, 0x023, 0x025, 0x029, 0x02d, 0x033, 0x039, 0x03c, 0x041, 0x043, - 0x04a, 0x04f, 0x052, 0x056, 0x05a, 0x05f, 0x063, 0x068, 0x06d, 0x072, - 0x077, 0x079, 0x07c, 0x080, 0x084, 0x088, 0x08e, 0x094, 0x09a, 0x09f, - 0x0a4, 0x0a9, 0x0ad, 0x0b1, 0x0b6, 0x0bc, 0x0be, 0x0c2, 0x0c8, 0x0cc, - 0x0d4, 0x0da, 0x0e0, 0x0e5, 0x0eb, 0x0f0, 0x0f5, 0x0f9, 0x0fe, 0x104, - 0x10c, 0x112, 0x118, 0x11e, 0x121, 0x129, 0x12c, 0x132, 0x13a, 0x13e, - 0x143, 0x148, 0x14d, 0x152, 0x157, 0x15a, 0x15f, 0x164, 0x166, 0x168, - 0x16d, 0x16f, 0x177, 0x17c, 0x182, 0x187, 0x18c, 0x18f, 0x193, 0x196, - 0x19b, 0x1a1, 0x1a9, 0x1af, 0x1b4, 0x1ba, 0x1be, 0x1c0, 0x1c4, 0x1ca, - 0x1d2, 0x1dd }; - -const unsigned char icon1[] = { - 255, 255, 255, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 255, 255, 255 }; - -char *ProgName; /* for AbEnd, later remove and use common/cmdline.h */ - -char *outputCName=NULL, *outputSName=NULL, *outputVName=NULL; -FILE *outputCFile, *outputSFile, *outputVFile; -int CFnum=0, SFnum=0, VFnum=0; -int forceFlag=0; -char outputCMode[2]="w"; -char outputSMode[2]="w"; -char outputVMode[2]="w"; diff --git a/src/grc/make/gcc.mak b/src/grc/make/gcc.mak deleted file mode 100644 index 285ae8f33..000000000 --- a/src/grc/make/gcc.mak +++ /dev/null @@ -1,58 +0,0 @@ -# -# gcc Makefile for grc -# - -# ------------------------------------------------------------------------------ - -# The executable to build -EXE = grc - -COMMON = ../common - -# -CC = gcc -CFLAGS = -g -O2 -Wall -W -std=c89 -override CFLAGS += -I$(COMMON) -LDFLAGS = -EBIND = emxbind - - -# ----------------------------------------------------------------------------- -# List of all object files - -OBJS = grc.o - -LIBS = $(COMMON)/common.a - -# ------------------------------------------------------------------------------ -# Makefile targets - -# Main target - must be first -.PHONY: all -ifeq (.depend,$(wildcard .depend)) -all: $(EXE) -include .depend -else -all: depend - @$(MAKE) -f make/gcc.mak all -endif - -$(EXE): $(OBJS) $(LIBS) - $(CC) $(LDFLAGS) $^ -o $@ - @if [ $(OS2_SHELL) ] ; then $(EBIND) $(EXE) ; fi - -clean: - $(RM) *~ core.* *.map - -zap: clean - $(RM) *.o $(EXE) .depend - -# ------------------------------------------------------------------------------ -# Make the dependencies - -.PHONY: depend dep -depend dep: $(OBJS:.o=.c) - @echo "Creating dependency information" - $(CC) $(CFLAGS) -MM $^ > .depend - - diff --git a/src/grc/make/watcom.mak b/src/grc/make/watcom.mak deleted file mode 100644 index 8895acbc8..000000000 --- a/src/grc/make/watcom.mak +++ /dev/null @@ -1,97 +0,0 @@ -# -# GRC Makefile for the Watcom compiler (using GNU make) -# - -# ------------------------------------------------------------------------------ -# Generic stuff - -# Environment variables for the watcom compiler -export WATCOM = c:\\watcom -export INCLUDE = $(WATCOM)\\h - -# We will use the windows compiler under linux (define as empty for windows) -export WINEDEBUG=fixme-all -WINE = wine - -# Programs -AR = $(WINE) wlib -CC = $(WINE) wcc386 -LD = $(WINE) wlink -WSTRIP = $(WINE) wstrip -q - -LNKCFG = ld.tmp - -# Program arguments -CFLAGS = -d1 -obeilr -zp4 -5 -zq -w2 -i=..\\common - -# Target files -EXE = grc.exe - -# Create NT programs by default -ifndef TARGET -TARGET = NT -endif - -# --------------------- OS2 --------------------- -ifeq ($(TARGET),OS2) -SYSTEM = os2v2 -CFLAGS += -bt=$(TARGET) -endif - -# -------------------- DOS4G -------------------- -ifeq ($(TARGET),DOS32) -SYSTEM = dos4g -CFLAGS += -bt=$(TARGET) -endif - -# --------------------- NT ---------------------- -ifeq ($(TARGET),NT) -SYSTEM = nt -CFLAGS += -bt=$(TARGET) -endif - -# ------------------------------------------------------------------------------ -# Implicit rules - -%.obj: %.c - $(CC) $(CFLAGS) -fo=$@ $^ - - -# ------------------------------------------------------------------------------ -# All OBJ files - -OBJS = grc.obj - -LIBS = ../common/common.lib - - -# ------------------------------------------------------------------------------ -# Main targets - -all: $(EXE) - - -# ------------------------------------------------------------------------------ -# Other targets - - -$(EXE): $(OBJS) $(LIBS) - @echo "DEBUG ALL" > $(LNKCFG) - @echo "OPTION QUIET" >> $(LNKCFG) - @echo "OPTION MAP" >> $(LNKCFG) - @echo "OPTION STACK=65536" >> $(LNKCFG) - @echo "NAME $@" >> $(LNKCFG) - @for i in $(OBJS); do echo "FILE $${i}"; done >> $(LNKCFG) - @for i in $(LIBS); do echo "LIBRARY $${i}"; done >> $(LNKCFG) - @$(LD) system $(SYSTEM) @$(LNKCFG) - @rm $(LNKCFG) - -clean: - @rm -f *~ core - -zap: clean - @rm -f $(OBJS) $(EXE) $(EXE:.exe=.map) - -strip: - @-$(WSTRIP) $(EXE) - diff --git a/src/grc65/grc65.c b/src/grc65/grc65.c new file mode 100644 index 000000000..ac5564632 --- /dev/null +++ b/src/grc65/grc65.c @@ -0,0 +1,738 @@ + +/* + GEOS resource compiler + + by Maciej 'YTM/Elysium' Witkowiak + + see GEOSLib documentation for license info + +*/ + +/* + - make it work, then do it better + - more or less comments? it was hard to code, should be even harder to + understand =D + - add loadable icons feature (binary - 63 bytes) +*/ + +/* - err, maybe free allocated memory, huh? (who cares, it's just a little prog...) +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <time.h> + +#include "grc65.h" + +/* common stuff */ +#include "fname.h" +#include "abend.h" +#include "chartype.h" +#include "xmalloc.h" + +void VLIRLinker(int argc, char *argv[]) { +FILE *outCVT, *input; +unsigned char *buffer; +unsigned char vlirtabt[127]; +unsigned char vlirtabs[127]; +int i,j,lastarg; +unsigned l; +int bytes; +int blocks,rest; + + i=2; + + /* check if we know enough */ + + if (argc<4) + AbEnd("too few arguments, required [out] [cvthead] [vlir0] ...\n"); + + /* first open and copy CVT header */ + + outCVT = fopen(argv[i],"wb+"); + if (outCVT==NULL) + AbEnd("can't open output:%s\n",strerror(errno)); + + ++i; + input = fopen(argv[i],"rb"); + if (input==NULL) + AbEnd("can't open input:%s\n",strerror(errno)); + + buffer = xmalloc(THIS_BUFFER_IS_SOOO_HUGE); + memset(buffer,0,THIS_BUFFER_IS_SOOO_HUGE); + + bytes = fread(buffer,1,1024,input); + fclose(input); + if (bytes!=508) + AbEnd("%s is not a cvt header\n",argv[i]); + + fwrite(buffer,1,bytes,outCVT); + + /* now put 254 bytes of VLIR table, to update later */ + + /* clear out things */ + memset(buffer,0,512); + fwrite(buffer,1,254,outCVT); + for (l=0;l<sizeof(vlirtabt)/sizeof(vlirtabt[0]);l++) { + vlirtabt[l]=0; + vlirtabs[l]=0; + } + + /* scan arguments for the last one that is not blank or nonexistant */ + j=argc; + lastarg=argc-1; + while (j!=3) { + --j; + if ((strcmp(argv[j],"blank")==0)||(strcmp(argv[j],"noexist")==0)) + --lastarg; + } + + /* now read all VLIR chains, align to 254 bytes */ + + ++i; + j=0; + while (i!=argc) { + if (strcmp(argv[i],"blank")==0) { + vlirtabt[j]=0; vlirtabs[j]=0; } + else if (strcmp(argv[i],"noexist")==0) { + vlirtabt[j]=0; vlirtabs[j]=0xff; } + else { + memset(buffer,0,bytes+512); + input = fopen(argv[i],"rb"); + if (input==NULL) + AbEnd("couldn't open %s:%s\n",argv[i],strerror(errno)); + bytes = fread(buffer,1,THIS_BUFFER_IS_SOOO_HUGE,input); + fclose(input); + if (bytes==0) + AbEnd("couldn't read %s:%s\n",argv[i],strerror(errno)); + blocks = bytes / 254; + rest = bytes % 254; + if (rest==0) { + rest = 255; + --blocks; + } else { + ++rest; + } + vlirtabt[j]=blocks+1; vlirtabs[j]=rest; + /* do not pad the last chain - it doesn't change or break anything + but filesize in bytes of .cvt will be identical to native cvt */ + if (i==lastarg) + fwrite(buffer,1,bytes,outCVT); + else + fwrite(buffer,1,(blocks+1)*254,outCVT); + } + ++j; + ++i; + } + + free(buffer); + + /* now rewind and update VLIR table */ + + fflush(outCVT); + fseek(outCVT,508,SEEK_SET); + for (l=0;l<sizeof(vlirtabt)/sizeof(vlirtabt[0]);l++) { + fputc(vlirtabt[l],outCVT); + fputc(vlirtabs[l],outCVT); + } + fclose(outCVT); + exit(EXIT_SUCCESS); +} + +void printCHeader (void) { + + fprintf(outputCFile, "\n/*\n\tThis file was generated by GEOS Resource Compiler\n" + "\n\tDO NOT EDIT! Any changes will be lost!\n" + "\n\tEdit proper resource file instead\n" + "\n*/\n\n"); +} + +void printSHeader (void) { + + fprintf(outputSFile, "\n;\n;\tThis file was generated by GEOS Resource Compiler\n;" + "\n;\tDO NOT EDIT! Any changes will be lost!\n;" + "\n;\tEdit proper resource file instead\n;" + "\n;\n\n"); +} + +void printVHeader (void) { + fprintf(outputVFile, "\n#\n#\tThis file was generated by GEOS Resource Compiler\n#" + "\n#\tDO NOT EDIT! Any changes will be lost!\n#" + "\n#\tEdit proper resource file instead\n#" + "\n#\tLook at end of this file to find commandline that must be used\n" + "#\tto invoke ld65 and grc65 (as VLIR linker)\n#" + "\n#\n\n"); +} + +void openCFile (void) { + if ((CFnum==0) && (forceFlag==0)) { + /* test if file exists already and no forcing*/ + if ((outputCFile = fopen (outputCName,"r"))!=0) + AbEnd("file %s already exists, aborting\n", outputCName); + } + if ((outputCFile = fopen (outputCName,outputCMode))==0) + AbEnd("can't open file %s for writing: %s\n",outputCName,strerror (errno)); + if (CFnum==0) { + outputCMode[0]='a'; + printCHeader(); + CFnum++; + } +} + +void openSFile (void) { + if ((SFnum==0) && (forceFlag==0)) { + /* test if file exists already and no forcing*/ + if ((outputSFile = fopen (outputSName,"r"))!=0) + AbEnd("file %s already exists, aborting\n", outputSName); + } + if ((outputSFile = fopen (outputSName,outputSMode))==0) + AbEnd("can't open file %s for writing: %s\n",outputSName,strerror (errno)); + if (SFnum==0) { + outputSMode[0]='a'; + printSHeader(); + SFnum++; + } +} + +void openVFile (void) { + if ((VFnum==0) && (forceFlag==0)) { + /* test if file exists already and no forcing*/ + if ((outputVFile = fopen (outputVName,"r"))!=0) + AbEnd("file %s already exists, aborting\n", outputVName); + } + if ((outputVFile = fopen (outputVName,outputVMode))==0) + AbEnd("can't open file %s for writting: %s\n",outputVName,strerror (errno)); + if (VFnum==0) { + outputVMode[0]='a'; + printVHeader(); + VFnum++; + } +} + +void printUsage (void) { + printf("Usage: %s [options] file\n" + "Options:\n" + "\t-h, -?\t\tthis help\n" + "\t-f\t\tforce writting files\n" + "\t-o name\t\tname C output file\n" + "\t-s name\t\tname asm output file\n" + "\t-l name\t\tname ld65 config output file (for vlir)\n" + "Or as VLIR linker: %s -vlir output.cvt header [vlir0] ... [blank] ... [vlir_n]\n", + ProgName,ProgName); +} + +int findToken (const char **tokenTbl, const char *token) { +/* takes as input table of tokens and token, returns position in table or -1 if not found */ +int a=0; + + while (strlen(tokenTbl[a])!=0) { + if (strcmp(tokenTbl[a],token)==0) break; + a++; + } + if (strlen(tokenTbl[a])==0) a=-1; + return a; +} + +char *nextPhrase() { + return strtok(NULL, "\""); + } + +char *nextWord() { + return strtok(NULL, " "); + } + +void setLen (char *name, unsigned len) { + if (strlen(name)>len) + name[len]='\0'; +} + +void fillOut (char *name, int len, char *filler) { +int a; + setLen (name, len); + fprintf(outputSFile, ".byte \"%s\"\n\t\t", name); + a = len - strlen(name); + if (a!=0) { + fprintf(outputSFile, ".byte %s", filler); + while (--a!=0) fprintf(outputSFile, ", %s", filler); + fprintf(outputSFile, "\n\t\t"); + } +} + +char *bintos(unsigned char a, char out[7]) { +int i=0; + for (;i<8;i++) { + out[7-i] = ((a & 1)==0) ? '0' : '1'; + a = a >> 1; }; + out[i]='\0'; +return out; +} + +int getNameSize (const char *word) { +/* count length of a word using BSW 9 font table */ +int a=0, i=0; + + while (word[i]!='\0') { + a+=(BSWTab[word[i]-31] - BSWTab[word[i]-32]); i++; } + + return a; +} + +void DoMenu (void) { + +int a, size, tmpsize, item=0; +char *token; +char namebuff[255]=""; +struct menu myMenu; +struct menuitem *curItem, *newItem; + + openCFile(); + + myMenu.name=nextWord(); + myMenu.left=atoi(nextWord()); + myMenu.top=atoi(nextWord()); + myMenu.type=nextWord(); + + if (strcmp(nextWord(),"{")!=0) { + AbEnd ("menu '%s' description has no opening bracket!\n", myMenu.name); + } + curItem = xmalloc(sizeof(struct menuitem)); + myMenu.item=curItem; + do { + token = nextWord(); + if (strcmp(token,"}")==0) break; + if (token[strlen(token)-1]!='"') { + strcpy (namebuff, token); + do { + token = nextWord(); + strcat (namebuff, " "); + strcat (namebuff, token); + } while (token[strlen(token)-1]!='"'); + token = xmalloc(strlen(namebuff)); + strcpy (token, namebuff); + } + curItem->name=token; + curItem->type=nextWord(); + curItem->target=nextWord(); + newItem=xmalloc(sizeof(struct menuitem)); + curItem->next=newItem; + curItem=newItem; + item++; + } while (strcmp(token,"}")!=0); + if (item==0) AbEnd ("menu '%s' has 0 items!\n", myMenu.name); + if (item>31) AbEnd ("menu '%s' has too many items!\n", myMenu.name); + + curItem->next=NULL; + + /* Count menu sizes */ + + size=0; + curItem=myMenu.item; + if (strstr(myMenu.type,"HORIZONTAL")!=NULL) { + /* menu is HORIZONTAL, ysize=15, sum xsize of all items +~8?*/ + myMenu.bot=myMenu.top+15; + for (a=0;a!=item;a++) { + size+=getNameSize(curItem->name); + curItem=curItem->next; + }; + } else { + /* menu is VERTICAL, ysize=item*15, count largest xsize of all items +~8? */ + myMenu.bot=myMenu.top+(14*item); + for (a=0;a!=item;a++) { + tmpsize=getNameSize(curItem->name); + size = (size > tmpsize) ? size : tmpsize; + curItem=curItem->next; + }; + }; + myMenu.right=myMenu.left+size-1; + + curItem=myMenu.item; + for (a=0;a!=item;a++) { + /* print prototype only if MENU_ACTION or DYN_SUB_MENU are present in type */ + if ((strstr(curItem->type, "MENU_ACTION")!=NULL) || (strstr(curItem->type, "DYN_SUB_MENU")!=NULL)) + fprintf(outputCFile, "void %s (void);\n", curItem->target); + curItem=curItem->next; + } + + fprintf(outputCFile, "\nconst void %s = {\n\t(char)%i, (char)%i,\n\t(int)%i, (int)%i,\n\t" + "(char)(%i | %s),\n", myMenu.name, myMenu.top, myMenu.bot, myMenu.left, + myMenu.right, item, myMenu.type); + + curItem=myMenu.item; + for (a=0;a!=item;a++) { + fprintf(outputCFile, "\t%s, (char)%s, (int)", curItem->name, curItem->type); + if ((strstr(curItem->type, "SUB_MENU")!=NULL) && (strstr(curItem->type, "DYN_SUB_MENU")==NULL)) + fprintf(outputCFile, "&"); + fprintf(outputCFile, "%s,\n", curItem->target); + curItem=curItem->next; + } + + fprintf(outputCFile, "\t};\n\n"); + + if (fclose (outputCFile)!=0) + AbEnd("error closing %s: %s\n",outputCName,strerror (errno)); +} + +void DoHeader (void) { + +time_t t; +struct tm *my_tm; + +struct appheader myHead; +char *token; +char i1[9], i2[9], i3[9]; +int a, b; + + openSFile(); + + token = nextWord(); + + a = findToken (hdrFTypes, token); + + switch (a) { + case 0: myHead.geostype = 6; break; + case 1: myHead.geostype = 14; break; + default: AbEnd("filetype '%s' is not supported yet\n", token); + } + + myHead.dosname = nextPhrase(); + nextPhrase(); + myHead.classname = nextPhrase(); + nextPhrase(); + myHead.version = nextPhrase(); + + /* put default values into myHead here */ + myHead.author = "cc65"; + myHead.info = "Program compiled with cc65 and GEOSLib."; + myHead.dostype = 128+3; + myHead.structure = 0; + myHead.mode = 0; + + t = time(NULL); + my_tm = localtime (&t); + + myHead.year = my_tm->tm_year; + myHead.month = my_tm->tm_mon+1; + myHead.day = my_tm->tm_mday; + myHead.hour = my_tm->tm_hour; + myHead.min = my_tm->tm_min; + + if (strcmp(nextWord(),"{")!=0) + AbEnd ("header '%s' has no opening bracket!\n", myHead.dosname); + + do { + token=nextWord(); + if (strcmp(token, "}")==0) break; + switch (a = findToken (hdrFields, token)) { + case -1: + AbEnd ("unknown field '%s' in header '%s'\n", token, myHead.dosname); + break; + case 0: /* author */ + myHead.author = nextPhrase(); break; + case 1: /* info */ + myHead.info = nextPhrase(); break; + case 2: /* date */ + myHead.year = atoi(nextWord()); + myHead.month = atoi(nextWord()); + myHead.day = atoi(nextWord()); + myHead.hour = atoi(nextWord()); + myHead.min = atoi(nextWord()); + break; + case 3: /* dostype */ + switch (b = findToken (hdrDOSTp, nextWord())) { + case -1: + AbEnd ("unknown dostype in header '%s'\n", myHead.dosname); + break; + default: + myHead.dostype = b/2 + 128 + 1; + break; + } + break; + case 4: /* mode */ + switch (b = findToken (hdrModes, nextWord())) { + case -1: + AbEnd ("unknown mode in header '%s'\n", myHead.dosname); + case 0: + myHead.mode = 0x40; break; + case 1: + myHead.mode = 0x00; break; + case 2: + myHead.mode = 0xc0; break; + case 3: + myHead.mode = 0x80; break; + } + break; + case 5: /* structure */ + switch (b = findToken(hdrStructTp, nextWord())) { + case -1: + AbEnd ("unknown structure type in header '%s'\n", myHead.dosname); + case 0: + case 1: + myHead.structure = 0; break; + case 2: + case 3: + myHead.structure = 1; break; + } + break; + } + + } while (strcmp(token, "}")!=0); + + /* OK, all information is gathered, do flushout */ + + fprintf(outputSFile, + "\t\t\t.segment \"HEADER\"\n\n\t\t.byte %i\n\t\t.word 0\n\t\t", myHead.dostype); + + fillOut(myHead.dosname,16,"$a0"); + + fprintf(outputSFile, + ".word 0\n\t\t.byte %i\n\t\t.byte %i\n\t\t.byte %i, %i, %i, %i, %i\n\n\t\t" + ".word 0\n\t\t.byte \"PRG formatted GEOS file V1.0\"\n\n\t\t.res $c4\n\n\t\t" + ".byte 3, 21, 63 | $80\n\t\t", + myHead.structure, myHead.geostype, myHead.year, myHead.month, myHead.day, + myHead.hour, myHead.min); + + for (a=0;a!=63;a=a+3) { + fprintf(outputSFile, + ".byte %%%s, %%%s, %%%s\n\t\t", + bintos(icon1[a], i1), bintos(icon1[a+1], i2), bintos(icon1[a+2], i3)); }; + + fprintf(outputSFile, + "\n\t\t.byte %i, %i, %i\n\t\t.word $0400, $0400-1, $0400\n\n\t\t", + myHead.dostype, myHead.geostype, myHead.structure); + + fillOut(myHead.classname,12,"$20"); + + fillOut(myHead.version,4,"0"); + + fprintf(outputSFile, + ".byte 0, 0, 0\n\t\t.byte %i\n\n\t\t", myHead.mode); + + setLen(myHead.author,62); + fprintf(outputSFile, + ".byte \"%s\"\n\t\t.byte 0\n\t\t.res (63-%i)\n\n\t\t", + myHead.author, (int) (strlen(myHead.author)+1)); + + setLen(myHead.info, 95); + fprintf(outputSFile, + ".byte \"%s\"\n\t\t.byte 0\n\t\t.res (96-%i)\n\n", + myHead.info, (int) (strlen(myHead.info)+1)); + + if (fclose (outputSFile)!=0) + AbEnd("error closing %s: %s\n",outputSName,strerror (errno)); + +} + +void DoVLIR (void) { + +char *token; +char *headname; +int i,numchains,vlirbase; +struct vlirentry { + char *chainname; + int exist; +}; + +struct vlirentry vlirtable[127]; + + openVFile(); + + headname = nextWord(); + + vlirbase = strtol(nextWord(),NULL,0); + + if (strcmp(nextWord(),"{")!=0) + AbEnd ("VLIR description has no opening bracket!\n"); + + numchains=0; + + do { + token=nextWord(); + if (strcmp(token, "}")==0) break; + numchains++; + if (numchains>127) { + AbEnd("Too many VLIR chains!\n"); + } + vlirtable[numchains].chainname=token; + + /* for first chain - name header */ + if (numchains==1) { + fprintf(outputVFile,"MEMORY {\n\tHEADER: start = $204, size = 508, file = \"%s\";\n" + "\tVLIR0: start = $0400, size = $5C00, file = \"%s\";\n",headname,token); + } else { + /* for all other - segment */ + /* ignore non-existing segments */ + vlirtable[numchains].exist=1; + if ( (strcmp(token,"blank")==0) || (strcmp(token,"noexist")==0) ) { + vlirtable[numchains].exist=0; + fprintf(outputVFile,"#"); + } + fprintf(outputVFile,"\tVLIR%i: start = $%x, size = $%x, file = \"%s\";\n", + numchains-1,vlirbase,0x5c00-vlirbase,token); + } + + } while (strcmp(token, "}")!=0); + fprintf(outputVFile,"}\n\n"); + + if (numchains==0) { + AbEnd("There must be at least one VLIR chain.\n"); + }; + + /* now put segments info */ + fprintf(outputVFile,"SEGMENTS {\n\tHEADER: load = HEADER, type = ro;\n" + "\tCODE: load = VLIR0, type = ro;\n" + "\tRODATA: load = VLIR0, type = ro;\n" + "\tDATA: load = VLIR0, type = rw;\n" + "\tBSS: load = VLIR0, type = bss, define = yes;\n\n"); + + for (i=2;i<=numchains;i++) { + if (vlirtable[i].exist==0) { + fprintf(outputVFile,"#"); + } + fprintf(outputVFile,"\tVLIR%i: load = VLIR%i, type = rw, define = yes;\n",i-1,i-1); + } + fprintf(outputVFile,"}\n"); + + /* now put usage info */ + fprintf(outputVFile,"\n# ld65 -o output.cvt -C %s file1.o file2.o ...",outputVName); + fprintf(outputVFile,"\n# grc65 -vlir outputname %s",headname); + for (i=1;i<=numchains;i++) { + fprintf(outputVFile," %s",vlirtable[i].chainname); + } + fprintf(outputVFile,"\n"); + + if (fclose (outputVFile)!=0) + AbEnd("error closing %s: %s\n",outputVName,strerror (errno)); +} + +char *filterInput (FILE *F, char *tbl) { +/* loads file into buffer filtering it out */ +int a, prevchar=-1, i=0, bracket=0, quote=1; + + while (1) { + a = getc(F); + if ((a=='\n')||(a=='\015')) a = ' '; + if (a==',' && quote) a = ' '; + if (a=='\042') quote=!quote; + if (quote) { + if ((a=='{')||(a=='(')) bracket++; + if ((a=='}')||(a==')')) bracket--; + } + if (a==EOF) { tbl[i]='\0'; xrealloc(tbl, i+1); break; }; + if (IsSpace(a)) { + if ((prevchar!=' ') && (prevchar!=-1)) { tbl[i++]=' '; prevchar=' '; } + } else { + if (a==';' && quote) { do { a = getc (F); } while (a!='\n'); fseek(F,-1,SEEK_CUR); } + else { + tbl[i++]=a; prevchar=a; } + } + } + + if (bracket!=0) AbEnd("there are unclosed brackets!\n"); + + return tbl; +} + +void processFile (const char *filename) { + +FILE *F; + +char *str; +char *token; + +int head=0; /* number of processed HEADER sections */ +int vlir=0; /* number of processed VLIR sections */ + + if ((F = fopen (filename,"r"))==0) + AbEnd("can't open file %s for reading: %s\n",filename,strerror (errno)); + + str=filterInput(F, xmalloc(BLOODY_BIG_BUFFER)); + + token = strtok (str," "); + + do { + if (str!=NULL) { + switch (findToken (mainToken, token)) { + + case 0: DoMenu(); break; + case 1: + if (++head!=1) { + AbEnd ("more than one HEADER section, aborting.\n"); + } else { + DoHeader(); + } + break; + case 2: break; /* icon not implemented yet */ + case 3: break; /* dialog not implemented yet */ + case 4: + if (++vlir!=1) { + AbEnd ("more than one VLIR section, aborting.\n"); + } else { + DoVLIR(); + } + break; + default: AbEnd ("unknown section %s.\n",token); break; + } + } + token = nextWord(); + } while (token!=NULL); +} + +int main(int argc, char *argv[]) { + +int ffile=0, i=1; + + ProgName = argv[0]; + while (i < argc) { + const char *arg = argv[i]; + if (arg[0] == '-') { + switch (arg[1]) { + case 'f': + forceFlag=1; + break; + case 'o': + outputCName=argv[++i]; + break; + case 's': + outputSName=argv[++i]; + break; + case 'l': + outputVName=argv[++i]; + break; + case 'h': + case '?': + printUsage(); + exit (EXIT_SUCCESS); + break; + case 'v': + if (strcmp(arg,"-vlir")==0) { + VLIRLinker(argc,argv); + exit (EXIT_SUCCESS); + break; + } else { + AbEnd("unknown option %s\n",arg); + break; + } + default: AbEnd("unknown option %s\n",arg); + } + } else { + ffile++; + + if (outputCName==NULL) + outputCName = MakeFilename(arg,".h"); + if (outputSName==NULL) + outputSName = MakeFilename(arg,".s"); + if (outputVName==NULL) + outputVName = MakeFilename(arg,".cfg"); + + processFile(arg); + + } + i++; + } + if (ffile==0) AbEnd("no input file\n"); + + return EXIT_SUCCESS; +} diff --git a/src/grc65/grc65.h b/src/grc65/grc65.h new file mode 100644 index 000000000..9825fe931 --- /dev/null +++ b/src/grc65/grc65.h @@ -0,0 +1,77 @@ + +/* I hope that no one will be able to create a .grc bigger than this... */ +#define BLOODY_BIG_BUFFER 65000 +/* there are no 6MB GEOS binaries... I hope! */ +#define THIS_BUFFER_IS_SOOO_HUGE 6000000 + +struct menuitem { + char *name; + char *type; + char *target; + struct menuitem *next; }; + +struct menu { + char *name; + int top, left; + int bot, right; + char *type; + struct menuitem *item; }; + +struct appheader { + int year,month,day,hour,min; + int mode; + int dostype; + int geostype; + int structure; + char *dosname; + char *classname; + char *version; + char *author; + char *info; }; + +const char *mainToken[] = { + "MENU", "HEADER", "ICON", "DIALOG", "VLIR", "" }; + +const char *hdrFTypes[] = { + "APPLICATION", "AUTO_EXEC", "DESK_ACC", "ASSEMBLY", "DISK_DEVICE", "PRINTER", "SYSTEM", "" }; + +const char *hdrFields[] = { + "author", "info", "date", "dostype", "mode", "structure", "" }; + +const char *hdrDOSTp[] = { + "seq", "SEQ", "prg", "PRG", "usr", "USR", "" }; + +const char *hdrStructTp[] = { + "seq", "SEQ", "vlir", "VLIR", "" }; + +const char *hdrModes[] = { + "any", "40only", "80only", "c64only", "" }; + +const int BSWTab[] = { 0, + 0x005, 0x007, 0x00b, 0x011, 0x017, + 0x01d, 0x023, 0x025, 0x029, 0x02d, 0x033, 0x039, 0x03c, 0x041, 0x043, + 0x04a, 0x04f, 0x052, 0x056, 0x05a, 0x05f, 0x063, 0x068, 0x06d, 0x072, + 0x077, 0x079, 0x07c, 0x080, 0x084, 0x088, 0x08e, 0x094, 0x09a, 0x09f, + 0x0a4, 0x0a9, 0x0ad, 0x0b1, 0x0b6, 0x0bc, 0x0be, 0x0c2, 0x0c8, 0x0cc, + 0x0d4, 0x0da, 0x0e0, 0x0e5, 0x0eb, 0x0f0, 0x0f5, 0x0f9, 0x0fe, 0x104, + 0x10c, 0x112, 0x118, 0x11e, 0x121, 0x129, 0x12c, 0x132, 0x13a, 0x13e, + 0x143, 0x148, 0x14d, 0x152, 0x157, 0x15a, 0x15f, 0x164, 0x166, 0x168, + 0x16d, 0x16f, 0x177, 0x17c, 0x182, 0x187, 0x18c, 0x18f, 0x193, 0x196, + 0x19b, 0x1a1, 0x1a9, 0x1af, 0x1b4, 0x1ba, 0x1be, 0x1c0, 0x1c4, 0x1ca, + 0x1d2, 0x1dd }; + +const unsigned char icon1[] = { + 255, 255, 255, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 255, 255, 255 }; + +char *ProgName; /* for AbEnd, later remove and use common/cmdline.h */ + +char *outputCName=NULL, *outputSName=NULL, *outputVName=NULL; +FILE *outputCFile, *outputSFile, *outputVFile; +int CFnum=0, SFnum=0, VFnum=0; +int forceFlag=0; +char outputCMode[2]="w"; +char outputSMode[2]="w"; +char outputVMode[2]="w"; diff --git a/src/grc65/make/gcc.mak b/src/grc65/make/gcc.mak new file mode 100644 index 000000000..2dd9f64ba --- /dev/null +++ b/src/grc65/make/gcc.mak @@ -0,0 +1,58 @@ +# +# gcc Makefile for grc +# + +# ------------------------------------------------------------------------------ + +# The executable to build +EXE = grc65 + +COMMON = ../common + +# +CC = gcc +CFLAGS = -g -O2 -Wall -W -std=c89 +override CFLAGS += -I$(COMMON) +LDFLAGS = +EBIND = emxbind + + +# ----------------------------------------------------------------------------- +# List of all object files + +OBJS = grc65.o + +LIBS = $(COMMON)/common.a + +# ------------------------------------------------------------------------------ +# Makefile targets + +# Main target - must be first +.PHONY: all +ifeq (.depend,$(wildcard .depend)) +all: $(EXE) +include .depend +else +all: depend + @$(MAKE) -f make/gcc.mak all +endif + +$(EXE): $(OBJS) $(LIBS) + $(CC) $(LDFLAGS) $^ -o $@ + @if [ $(OS2_SHELL) ] ; then $(EBIND) $(EXE) ; fi + +clean: + $(RM) *~ core.* *.map + +zap: clean + $(RM) *.o $(EXE) .depend + +# ------------------------------------------------------------------------------ +# Make the dependencies + +.PHONY: depend dep +depend dep: $(OBJS:.o=.c) + @echo "Creating dependency information" + $(CC) $(CFLAGS) -MM $^ > .depend + + diff --git a/src/grc65/make/watcom.mak b/src/grc65/make/watcom.mak new file mode 100644 index 000000000..84a9f2faf --- /dev/null +++ b/src/grc65/make/watcom.mak @@ -0,0 +1,97 @@ +# +# GRC Makefile for the Watcom compiler (using GNU make) +# + +# ------------------------------------------------------------------------------ +# Generic stuff + +# Environment variables for the watcom compiler +export WATCOM = c:\\watcom +export INCLUDE = $(WATCOM)\\h + +# We will use the windows compiler under linux (define as empty for windows) +export WINEDEBUG=fixme-all +WINE = wine + +# Programs +AR = $(WINE) wlib +CC = $(WINE) wcc386 +LD = $(WINE) wlink +WSTRIP = $(WINE) wstrip -q + +LNKCFG = ld.tmp + +# Program arguments +CFLAGS = -d1 -obeilr -zp4 -5 -zq -w2 -i=..\\common + +# Target files +EXE = grc65.exe + +# Create NT programs by default +ifndef TARGET +TARGET = NT +endif + +# --------------------- OS2 --------------------- +ifeq ($(TARGET),OS2) +SYSTEM = os2v2 +CFLAGS += -bt=$(TARGET) +endif + +# -------------------- DOS4G -------------------- +ifeq ($(TARGET),DOS32) +SYSTEM = dos4g +CFLAGS += -bt=$(TARGET) +endif + +# --------------------- NT ---------------------- +ifeq ($(TARGET),NT) +SYSTEM = nt +CFLAGS += -bt=$(TARGET) +endif + +# ------------------------------------------------------------------------------ +# Implicit rules + +%.obj: %.c + $(CC) $(CFLAGS) -fo=$@ $^ + + +# ------------------------------------------------------------------------------ +# All OBJ files + +OBJS = grc65.obj + +LIBS = ../common/common.lib + + +# ------------------------------------------------------------------------------ +# Main targets + +all: $(EXE) + + +# ------------------------------------------------------------------------------ +# Other targets + + +$(EXE): $(OBJS) $(LIBS) + @echo "DEBUG ALL" > $(LNKCFG) + @echo "OPTION QUIET" >> $(LNKCFG) + @echo "OPTION MAP" >> $(LNKCFG) + @echo "OPTION STACK=65536" >> $(LNKCFG) + @echo "NAME $@" >> $(LNKCFG) + @for i in $(OBJS); do echo "FILE $${i}"; done >> $(LNKCFG) + @for i in $(LIBS); do echo "LIBRARY $${i}"; done >> $(LNKCFG) + @$(LD) system $(SYSTEM) @$(LNKCFG) + @rm $(LNKCFG) + +clean: + @rm -f *~ core + +zap: clean + @rm -f $(OBJS) $(EXE) $(EXE:.exe=.map) + +strip: + @-$(WSTRIP) $(EXE) + diff --git a/src/make/gcc.mak b/src/make/gcc.mak index ccd1f3fa7..b5955597f 100644 --- a/src/make/gcc.mak +++ b/src/make/gcc.mak @@ -9,7 +9,7 @@ PROGS = \ cl65 \ co65 \ da65 \ - grc \ + grc65 \ ld65 \ od65