mirror of
https://github.com/cc65/cc65.git
synced 2025-01-29 21:31:53 +00:00
Created C1P object file generator.
This commit is contained in:
parent
c6f97e914c
commit
9b505d7b65
@ -1,6 +1,7 @@
|
||||
ifeq ($(shell echo),)
|
||||
|
||||
PROGS = ar65 \
|
||||
c1p65 \
|
||||
ca65 \
|
||||
cc65 \
|
||||
cl65 \
|
||||
|
94
src/c1p65.vcxproj
Normal file
94
src/c1p65.vcxproj
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="c1p65\main.c" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4E031DE0-82B4-4204-8529-536626F7E0DF}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>c1p65</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>
|
||||
</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>
|
||||
</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)..\bin\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)..\bin\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>common</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>common</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
219
src/c1p65/main.c
Normal file
219
src/c1p65/main.c
Normal file
@ -0,0 +1,219 @@
|
||||
/* Object file conversion utility for Challenger 1P
|
||||
|
||||
by Stephan Muehlstrasser
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
/* common stuff */
|
||||
#include "abend.h"
|
||||
#include "cmdline.h"
|
||||
#include "fname.h"
|
||||
#include "chartype.h"
|
||||
#include "target.h"
|
||||
#include "version.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
static void Usage (void)
|
||||
{
|
||||
printf (
|
||||
"Usage: %s [options] file\n"
|
||||
"Short options:\n"
|
||||
" -V\t\t\tPrint the version number\n"
|
||||
" -h\t\t\tHelp (this text)\n"
|
||||
" -o name\t\tName the C1P output file (default: <input.c1p>)\n"
|
||||
" -S addr\t\tLoad address (default 0x400)\n"
|
||||
"\n"
|
||||
"Long options:\n"
|
||||
" --help\t\tHelp (this text)\n"
|
||||
" --version\t\tPrint the version number\n",
|
||||
ProgName);
|
||||
}
|
||||
|
||||
static void OptHelp (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Print usage information and exit */
|
||||
{
|
||||
Usage ();
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static void OptVersion (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Print the program version */
|
||||
{
|
||||
fprintf (stderr, "grc65 V%s\n", GetVersionAsString ());
|
||||
}
|
||||
|
||||
|
||||
static unsigned long CvtNumber (const char* Arg, const char* Number)
|
||||
/* Convert a number from a string. Allow '$' and '0x' prefixes for hex
|
||||
* numbers. Duplicated from ld65's main.c.
|
||||
*/
|
||||
{
|
||||
unsigned long Val;
|
||||
int Converted;
|
||||
|
||||
/* Convert */
|
||||
if (*Number == '$') {
|
||||
++Number;
|
||||
Converted = sscanf (Number, "%lx", &Val);
|
||||
} else {
|
||||
Converted = sscanf (Number, "%li", (long*)&Val);
|
||||
}
|
||||
|
||||
/* Check if we do really have a number */
|
||||
if (Converted != 1) {
|
||||
AbEnd ("Invalid number given in argument: %s\n", Arg);
|
||||
}
|
||||
|
||||
/* Return the result */
|
||||
return Val;
|
||||
}
|
||||
|
||||
/* Commands of C1P PROM monitor */
|
||||
#define ADDRESS_MODE_CMD '.'
|
||||
#define DATA_MODE_CMD '/'
|
||||
#define EXECUTE_CMD 'G'
|
||||
|
||||
/* Transform the cc65 executable binary into a series of
|
||||
commands that make the C1P PROM monitor load the bytes
|
||||
into memory.
|
||||
*/
|
||||
static void Transform (unsigned long StartAddress, FILE *In, FILE *Out)
|
||||
{
|
||||
int c;
|
||||
unsigned long CurrentAddress;
|
||||
|
||||
/* Loop over all input bytes, position to current address,
|
||||
switch to data mod, output input byte
|
||||
*/
|
||||
for (CurrentAddress = StartAddress, c = getc(In);
|
||||
c != EOF;
|
||||
c = getc(In), CurrentAddress += 1) {
|
||||
fprintf (Out, "%c%04.4X%c%02.2X",
|
||||
ADDRESS_MODE_CMD, (unsigned int) CurrentAddress & 0xFFFF,
|
||||
DATA_MODE_CMD, (unsigned int) c & 0xFF);
|
||||
}
|
||||
|
||||
/* And execute
|
||||
fprintf (Out, "%c%04.4x%c",
|
||||
ADDRESS_MODE_CMD, (unsigned int) StartAddress & 0xFFFF,
|
||||
EXECUTE_CMD);
|
||||
*/
|
||||
}
|
||||
|
||||
/* Default suffix for C1P object file */
|
||||
#define C1P_SUFFIX ".c1p"
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
/* Program long options */
|
||||
static const LongOpt OptTab[] = {
|
||||
{ "--help", 0, OptHelp},
|
||||
{ "--version", 0, OptVersion},
|
||||
};
|
||||
|
||||
/* Initialize input and output file name */
|
||||
const char* InputFile = 0;
|
||||
const char* OutputFile = 0;
|
||||
char *GeneratedOutputFile = 0;
|
||||
|
||||
/* Initialize file pointers */
|
||||
FILE *InputFileFp = 0;
|
||||
FILE *OutputFileFp = 0;
|
||||
|
||||
/* Initialize with default start address defined in c1p.cfg */
|
||||
unsigned long StartAddr = 0x400;
|
||||
|
||||
unsigned int I;
|
||||
|
||||
/* Initialize the cmdline module */
|
||||
InitCmdLine (&argc, &argv, "c1p65");
|
||||
|
||||
/* Check the parameters */
|
||||
I = 1;
|
||||
while (I < ArgCount) {
|
||||
|
||||
/* Get the argument */
|
||||
const char* Arg = ArgVec [I];
|
||||
|
||||
/* Check for an option */
|
||||
if (Arg[0] == '-') {
|
||||
switch (Arg[1]) {
|
||||
|
||||
case '-':
|
||||
LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
OutputFile = GetArg (&I, 2);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
StartAddr = CvtNumber (Arg, GetArg (&I, 2));
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
OptHelp (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
OptVersion (Arg, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
UnknownOption (Arg);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (InputFile) {
|
||||
fprintf (stderr, "additional file specs ignored\n");
|
||||
} else {
|
||||
InputFile = Arg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Next argument */
|
||||
++I;
|
||||
}
|
||||
|
||||
if (!InputFile) AbEnd ("No input file");
|
||||
|
||||
if (!OutputFile) {
|
||||
const size_t len = strlen(InputFile) + sizeof(C1P_SUFFIX);
|
||||
|
||||
GeneratedOutputFile = (char *) xmalloc(len);
|
||||
sprintf(GeneratedOutputFile, "%s%s", InputFile, C1P_SUFFIX);
|
||||
OutputFile = GeneratedOutputFile;
|
||||
}
|
||||
|
||||
/* Open input and output files */
|
||||
InputFileFp = fopen(InputFile, "rb");
|
||||
if (!InputFileFp) AbEnd ("Unable to open input file");
|
||||
|
||||
OutputFileFp = fopen(OutputFile, "wb");
|
||||
if (!OutputFileFp) AbEnd ("Unable to open output file");
|
||||
|
||||
/* Generate object file */
|
||||
Transform (StartAddr, InputFileFp, OutputFileFp);
|
||||
|
||||
/* Cleanup */
|
||||
if (fclose(InputFileFp) == EOF) AbEnd ("Error closing input file");
|
||||
|
||||
if (fclose(OutputFileFp) == EOF) AbEnd ("Error closing output file");
|
||||
|
||||
if (GeneratedOutputFile) {
|
||||
xfree(GeneratedOutputFile);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user