mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
Turned sim65 into a lightweight cc65 execution environment.
The sim65 source code has been a construction site for over a decade. I was looking for a simple cc65 program execution environment for regression tests. So I decided to re-purpose sim65 for that task by removing about everything but the 6502 emulation. There's no memory mapped i/o emulation whatsoever. Rather exit(), open(), close(), read() and write() calls are supported by mapping them through a thin paravirtualization layer to the corresponding host os functions. Note: The sim65 6502 emulation provides means to switch between 6502 and 65C02 emulation but currently there are no actual 65C02 opcodes implemented.
This commit is contained in:
parent
753aa29b15
commit
3a028fb621
@ -9,6 +9,7 @@ PROGS = ar65 \
|
||||
grc65 \
|
||||
ld65 \
|
||||
od65 \
|
||||
sim65 \
|
||||
sp65
|
||||
|
||||
CA65_INC := $(abspath ../asminc)
|
||||
|
@ -53,6 +53,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sp65", "sp65.vcxproj", "{43
|
||||
{71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sim65", "sim65.vcxproj", "{002A366E-2863-46A8-BDDE-DDF534AAEC73}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@ -103,6 +108,10 @@ Global
|
||||
{4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}.Release|Win32.Build.0 = Release|Win32
|
||||
{002A366E-2863-46A8-BDDE-DDF534AAEC73}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{002A366E-2863-46A8-BDDE-DDF534AAEC73}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{002A366E-2863-46A8-BDDE-DDF534AAEC73}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{002A366E-2863-46A8-BDDE-DDF534AAEC73}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
96
src/sim65.vcxproj
Normal file
96
src/sim65.vcxproj
Normal file
@ -0,0 +1,96 @@
|
||||
<?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>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{002A366E-2863-46A8-BDDE-DDF534AAEC73}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>sim65</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</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;_CONSOLE;_DEBUG</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>common</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</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;_CONSOLE;NDEBUG</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>common</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="sim65\6502.h" />
|
||||
<ClInclude Include="sim65\error.h" />
|
||||
<ClInclude Include="sim65\memory.h" />
|
||||
<ClInclude Include="sim65\paravirt.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="sim65\6502.c" />
|
||||
<ClCompile Include="sim65\error.c" />
|
||||
<ClCompile Include="sim65\main.c" />
|
||||
<ClCompile Include="sim65\memory.c" />
|
||||
<ClCompile Include="sim65\paravirt.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
2830
src/sim65/6502.c
Normal file
2830
src/sim65/6502.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* addrspace.h */
|
||||
/* 6502.h */
|
||||
/* */
|
||||
/* CPU address space for the 6502 simulator */
|
||||
/* CPU core for the 6502 */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
@ -33,8 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#ifndef ADDRSPACE_H
|
||||
#define ADDRSPACE_H
|
||||
#ifndef _6502_H
|
||||
#define _6502_H
|
||||
|
||||
|
||||
|
||||
@ -44,20 +44,36 @@
|
||||
|
||||
|
||||
|
||||
/* Forwards */
|
||||
struct CPUData;
|
||||
struct ChipInstance;
|
||||
/* Supported CPUs */
|
||||
typedef enum CPUType {
|
||||
CPU_6502,
|
||||
CPU_65C02
|
||||
} CPUType;
|
||||
|
||||
/* Forwards */
|
||||
typedef struct AddressSpace AddressSpace;
|
||||
struct AddressSpace {
|
||||
|
||||
struct CPU* CPU; /* Backpointer to CPU */
|
||||
unsigned Size; /* Address space size */
|
||||
struct ChipInstance* Data[1]; /* Pointer to chips, dynamically! */
|
||||
/* Current CPU */
|
||||
extern CPUType CPU;
|
||||
|
||||
/* 6502 CPU registers */
|
||||
typedef struct CPURegs CPURegs;
|
||||
struct CPURegs {
|
||||
unsigned AC; /* Accumulator */
|
||||
unsigned XR; /* X register */
|
||||
unsigned YR; /* Y register */
|
||||
unsigned ZR; /* Z register */
|
||||
unsigned SR; /* Status register */
|
||||
unsigned SP; /* Stackpointer */
|
||||
unsigned PC; /* Program counter */
|
||||
};
|
||||
|
||||
/* Status register bits */
|
||||
#define CF 0x01 /* Carry flag */
|
||||
#define ZF 0x02 /* Zero flag */
|
||||
#define IF 0x04 /* Interrupt flag */
|
||||
#define DF 0x08 /* Decimal flag */
|
||||
#define BF 0x10 /* Break flag */
|
||||
#define OF 0x40 /* Overflow flag */
|
||||
#define SF 0x80 /* Sign flag */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -66,34 +82,25 @@ struct AddressSpace {
|
||||
|
||||
|
||||
|
||||
AddressSpace* NewAddressSpace (unsigned Size);
|
||||
/* Allocate a new address space and return it */
|
||||
void Reset (void);
|
||||
/* Generate a CPU RESET */
|
||||
|
||||
void ASWrite (AddressSpace* AS, unsigned Addr, unsigned char Val);
|
||||
/* Write a byte to a given location */
|
||||
void IRQRequest (void);
|
||||
/* Generate an IRQ */
|
||||
|
||||
unsigned char ASRead (AddressSpace* AS, unsigned Addr);
|
||||
/* Read a byte from a location */
|
||||
void NMIRequest (void);
|
||||
/* Generate an NMI */
|
||||
|
||||
void ASWriteCtrl (AddressSpace* AS, unsigned Addr, unsigned char Val);
|
||||
/* Write a byte to a given location */
|
||||
unsigned ExecuteInsn (void);
|
||||
/* Execute one CPU instruction. Return the number of clock cycles for the
|
||||
* executed instruction.
|
||||
*/
|
||||
|
||||
unsigned char ASReadCtrl (AddressSpace* AS, unsigned Addr);
|
||||
/* Read a byte from a location */
|
||||
|
||||
void ASAssignChip (AddressSpace* AS, struct ChipInstance* CI,
|
||||
unsigned Addr, unsigned Range);
|
||||
/* Assign a chip instance to memory locations */
|
||||
|
||||
struct ChipInstance* ASGetChip (const AddressSpace* AS, unsigned Addr);
|
||||
/* Get the chip that is located at the given address (may return NULL). */
|
||||
unsigned long GetCycles (void);
|
||||
/* Return the total number of clock cycles executed */
|
||||
|
||||
|
||||
|
||||
/* End of addrspace.h */
|
||||
/* End of 6502.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -1,190 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* addrspace.c */
|
||||
/* */
|
||||
/* CPU address space for the 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chip.h"
|
||||
#include "cpucore.h"
|
||||
#include "error.h"
|
||||
#include "addrspace.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
AddressSpace* NewAddressSpace (unsigned Size)
|
||||
/* Allocate a new address space and return it */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Allocate memory */
|
||||
AddressSpace* AS = xmalloc (sizeof (AddressSpace) +
|
||||
(Size - 1) * sizeof (ChipInstance*));
|
||||
|
||||
/* Initialize the struct */
|
||||
AS->CPU = 0;
|
||||
AS->Size = Size;
|
||||
for (I = 0; I < Size; ++I) {
|
||||
AS->Data[I] = 0;
|
||||
}
|
||||
|
||||
/* Return the new struct */
|
||||
return AS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ASWrite (AddressSpace* AS, unsigned Addr, unsigned char Val)
|
||||
/* Write a byte to a given location */
|
||||
{
|
||||
const ChipInstance* CI;
|
||||
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr < AS->Size);
|
||||
|
||||
/* Get the instance of the chip at this address */
|
||||
CI = AS->Data[Addr];
|
||||
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Break ("Writing to unassigned memory at $%06X", Addr);
|
||||
} else {
|
||||
CI->C->Data->Write (CI->Data, Addr - CI->Addr, Val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char ASRead (AddressSpace* AS, unsigned Addr)
|
||||
/* Read a byte from a location */
|
||||
{
|
||||
const ChipInstance* CI;
|
||||
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr < AS->Size);
|
||||
|
||||
/* Get the instance of the chip at this address */
|
||||
CI = AS->Data[Addr];
|
||||
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Break ("Reading from unassigned memory at $%06X", Addr);
|
||||
return 0xFF;
|
||||
} else {
|
||||
return CI->C->Data->Read (CI->Data, Addr - CI->Addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ASWriteCtrl (AddressSpace* AS, unsigned Addr, unsigned char Val)
|
||||
/* Write a byte to a given location */
|
||||
{
|
||||
const ChipInstance* CI;
|
||||
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr < AS->Size);
|
||||
|
||||
/* Get the instance of the chip at this address */
|
||||
CI = AS->Data[Addr];
|
||||
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Break ("Writing to unassigned memory at $%06X", Addr);
|
||||
} else {
|
||||
CI->C->Data->WriteCtrl (CI->Data, Addr - CI->Addr, Val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char ASReadCtrl (AddressSpace* AS, unsigned Addr)
|
||||
/* Read a byte from a location */
|
||||
{
|
||||
const ChipInstance* CI;
|
||||
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr < AS->Size);
|
||||
|
||||
/* Get the instance of the chip at this address */
|
||||
CI = AS->Data[Addr];
|
||||
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Break ("Reading from unassigned memory at $%06X", Addr);
|
||||
return 0xFF;
|
||||
} else {
|
||||
return CI->C->Data->ReadCtrl (CI->Data, Addr - CI->Addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ASAssignChip (AddressSpace* AS, ChipInstance* CI,
|
||||
unsigned Addr, unsigned Range)
|
||||
/* Assign a chip instance to memory locations */
|
||||
{
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr + Range <= AS->Size);
|
||||
|
||||
/* Assign the chip instance */
|
||||
while (Range--) {
|
||||
CHECK (AS->Data[Addr] == 0);
|
||||
AS->Data[Addr++] = CI;
|
||||
}
|
||||
|
||||
/* Set the backpointer to us */
|
||||
CI->AS = AS;
|
||||
}
|
||||
|
||||
|
||||
ChipInstance* ASGetChip (const AddressSpace* AS, unsigned Addr)
|
||||
/* Get the chip that is located at the given address (may return NULL). */
|
||||
{
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr < AS->Size);
|
||||
|
||||
/* Return the chip instance */
|
||||
return AS->Data[Addr];
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,191 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* callback.c */
|
||||
/* */
|
||||
/* Chip callbacks */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "error.h"
|
||||
#include "callback.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
struct Callback {
|
||||
Callback* Next; /* Next entry in list */
|
||||
unsigned Ticks; /* Remaining ticks */
|
||||
CallbackFunc UserFunc; /* User function */
|
||||
void* UserData; /* User data */
|
||||
};
|
||||
|
||||
/* Delta list that keeps existing callbacks */
|
||||
static Callback* List = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Routines that handle the delta list */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void InsertCallback (Callback* C, unsigned Ticks)
|
||||
/* Insert the callback C into the delta list */
|
||||
{
|
||||
/* Search for the insertion point */
|
||||
Callback* N;
|
||||
Callback** L = &List;
|
||||
while ((N = *L) != 0) {
|
||||
/* Check if the next callback in the list has a higher wait time */
|
||||
if (N->Ticks > Ticks) {
|
||||
/* Insert before this callback */
|
||||
N->Ticks -= Ticks;
|
||||
break;
|
||||
} else {
|
||||
/* Insert behind this callback */
|
||||
Ticks -= N->Ticks;
|
||||
L = &N->Next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert the new task */
|
||||
C->Ticks = Ticks;
|
||||
C->Next = N;
|
||||
*L = C;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void RemoveCallback (Callback* C)
|
||||
/* Remove a callback from the list. If the callback is not in the list, this
|
||||
* is a fatal error.
|
||||
*/
|
||||
{
|
||||
Callback* N;
|
||||
Callback** L = &List;
|
||||
while ((N = *L) != 0) {
|
||||
if (N == C) {
|
||||
/* Found, remove it */
|
||||
if (C->Next) {
|
||||
/* Adjust the counter of the following callback */
|
||||
C->Next->Ticks += C->Ticks;
|
||||
}
|
||||
*L = C->Next;
|
||||
return;
|
||||
} else {
|
||||
L = &N->Next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback was not found */
|
||||
Internal ("RemoveCallback: Callback not found in list!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
Callback* NewCallback (unsigned Ticks, CallbackFunc Func, void* Data)
|
||||
/* Create a callback for function F to be called in Ticks ticks. */
|
||||
{
|
||||
/* Allocate memory */
|
||||
Callback* C = xmalloc (sizeof (Callback));
|
||||
|
||||
/* Initialize the fields */
|
||||
C->UserFunc = Func;
|
||||
C->UserData = Data;
|
||||
|
||||
/* Insert the callback into the delta list */
|
||||
InsertCallback (C, Ticks);
|
||||
|
||||
/* Return the new callback */
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FreeCallback (Callback* C)
|
||||
/* Delete a callback (remove from the queue) */
|
||||
{
|
||||
/* Remove the callback from the list */
|
||||
RemoveCallback (C);
|
||||
|
||||
/* Delete it */
|
||||
xfree (C);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HandleCallbacks (unsigned TicksSinceLastCall)
|
||||
/* Handle the callback queue */
|
||||
{
|
||||
while (List) {
|
||||
|
||||
/* Check if this one is due */
|
||||
if (List->Ticks <= TicksSinceLastCall) {
|
||||
|
||||
/* Calclulate the tick offset */
|
||||
int TickOffs = ((int) List->Ticks) - ((int) TicksSinceLastCall);
|
||||
|
||||
/* Retrieve the first callback from the list */
|
||||
Callback* C = List;
|
||||
List = C->Next;
|
||||
|
||||
/* Call the user function */
|
||||
C->UserFunc (TickOffs, C->UserData);
|
||||
|
||||
/* Delete the callback */
|
||||
xfree (C);
|
||||
|
||||
} else {
|
||||
|
||||
List->Ticks -= TicksSinceLastCall;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* callback.h */
|
||||
/* */
|
||||
/* Chip callbacks */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CALLBACK_H
|
||||
#define CALLBACK_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Type of a callback function */
|
||||
typedef void (*CallbackFunc) (int TickOffs, void* UserData);
|
||||
|
||||
/* Forward */
|
||||
typedef struct Callback Callback;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
Callback* NewCallback (unsigned Ticks, CallbackFunc Func, void* Data);
|
||||
/* Create a callback for function F to be called in Ticks ticks. */
|
||||
|
||||
void FreeCallback (Callback* C);
|
||||
/* Delete a callback (remove from the queue) */
|
||||
|
||||
void HandleCallbacks (unsigned TicksSinceLastCall);
|
||||
/* Handle the callback queue */
|
||||
|
||||
|
||||
|
||||
/* End of callback.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,234 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* cfgdata.c */
|
||||
/* */
|
||||
/* Config data structure */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "strutil.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "error.h"
|
||||
#include "scanner.h"
|
||||
#include "cfgdata.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
CfgData* NewCfgData (void)
|
||||
/* Create and intialize a new CfgData struct, then return it. The function
|
||||
* uses the current output of the config scanner.
|
||||
*/
|
||||
{
|
||||
/* Allocate memory */
|
||||
CfgData* D = xmalloc (sizeof (CfgData) + SB_GetLen (&CfgSVal));
|
||||
|
||||
/* Initialize the fields */
|
||||
D->Type = CfgDataInvalid;
|
||||
D->Line = CfgErrorLine;
|
||||
D->Col = CfgErrorCol;
|
||||
memcpy (D->Attr, SB_GetConstBuf (&CfgSVal), SB_GetLen (&CfgSVal) + 1);
|
||||
|
||||
/* Return the new struct */
|
||||
return D;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FreeCfgData (CfgData* D)
|
||||
/* Free a config data structure */
|
||||
{
|
||||
if (D->Type == CfgDataId || D->Type == CfgDataString) {
|
||||
/* Free the string value */
|
||||
xfree (D->V.SVal);
|
||||
}
|
||||
/* Free the structure */
|
||||
xfree (D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgDataCheckType (const CfgData* D, unsigned Type)
|
||||
/* Check the config data type and print an error message if it has the wrong
|
||||
* type.
|
||||
*/
|
||||
{
|
||||
if (D->Type != Type) {
|
||||
Error ("%s(%u): Attribute `%s' has invalid type",
|
||||
CfgGetName (), D->Line, D->Attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CfgDataFind (const Collection* Attributes, const char* AttrName)
|
||||
/* Find the attribute with the given name and return its index. Return -1 if
|
||||
* the attribute was not found.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Walk through the attributes checking for a "mirror" attribute */
|
||||
for (I = 0; I < CollCount (Attributes); ++I) {
|
||||
|
||||
/* Get the next attribute */
|
||||
const CfgData* D = CollConstAt (Attributes, I);
|
||||
|
||||
/* Compare the name */
|
||||
if (StrCaseCmp (D->Attr, AttrName) == 0) {
|
||||
/* Found */
|
||||
return I;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CfgData* CfgDataGetTyped (Collection* Attributes, const char* Name, unsigned Type)
|
||||
/* Find the attribute with the given name and type. If found, remove it from
|
||||
* Attributes and return it. If not found or wrong type, return NULL.
|
||||
*/
|
||||
{
|
||||
CfgData* D;
|
||||
|
||||
/* Search for the attribute */
|
||||
int I = CfgDataFind (Attributes, Name);
|
||||
if (I < 0) {
|
||||
/* Not found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the attribute */
|
||||
D = CollAtUnchecked (Attributes, I);
|
||||
|
||||
/* Check the type */
|
||||
if (D->Type != Type) {
|
||||
/* Wrong type. ### Warn here? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove the attribute and return it */
|
||||
CollDelete (Attributes, I);
|
||||
return D;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CfgDataGetId (Collection* Attributes, const char* Name, char** Id)
|
||||
/* Search CfgInfo for an attribute with the given name and type "id". If
|
||||
* found, remove it from the configuration, copy it into Buf and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
{
|
||||
CfgData* D = CfgDataGetTyped (Attributes, Name, CfgDataId);
|
||||
if (D == 0) {
|
||||
/* Not found or wrong type */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use the string value and invalidate the type, so FreeCfgData won't
|
||||
* delete the string.
|
||||
*/
|
||||
*Id = D->V.SVal;
|
||||
D->Type = CfgDataInvalid;
|
||||
|
||||
/* Delete the config data struct */
|
||||
FreeCfgData (D);
|
||||
|
||||
/* Success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CfgDataGetStr (Collection* Attributes, const char* Name, char** S)
|
||||
/* Search CfgInfo for an attribute with the given name and type "string".
|
||||
* If found, remove it from the configuration, copy it into Buf and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
{
|
||||
CfgData* D = CfgDataGetTyped (Attributes, Name, CfgDataString);
|
||||
if (D == 0) {
|
||||
/* Not found or wrong type */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use the string value and invalidate the type, so FreeCfgData won't
|
||||
* delete the string.
|
||||
*/
|
||||
*S = D->V.SVal;
|
||||
D->Type = CfgDataInvalid;
|
||||
|
||||
/* Delete the config data struct */
|
||||
FreeCfgData (D);
|
||||
|
||||
/* Success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CfgDataGetNum (Collection* Attributes, const char* Name, long* Val)
|
||||
/* Search CfgInfo for an attribute with the given name and type "number".
|
||||
* If found, remove it from the configuration, copy it into Val and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
{
|
||||
CfgData* D = CfgDataGetTyped (Attributes, Name, CfgDataNumber);
|
||||
if (D == 0) {
|
||||
/* Not found or wrong type */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the value to the caller */
|
||||
*Val = D->V.IVal;
|
||||
|
||||
/* Delete the config data struct */
|
||||
FreeCfgData (D);
|
||||
|
||||
/* Success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,120 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* cfgdata.h */
|
||||
/* */
|
||||
/* Config data structure */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CFGDATA_H
|
||||
#define CFGDATA_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
typedef struct CfgData CfgData;
|
||||
struct CfgData {
|
||||
enum {
|
||||
CfgDataInvalid,
|
||||
CfgDataId,
|
||||
CfgDataNumber,
|
||||
CfgDataString
|
||||
} Type; /* Type of the value */
|
||||
union {
|
||||
char* SVal; /* String or id value */
|
||||
long IVal; /* Integer value */
|
||||
} V;
|
||||
unsigned Line; /* Line where the attribute was defined */
|
||||
unsigned Col; /* Column of attribute definition */
|
||||
char Attr[1]; /* The attribute name */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
CfgData* NewCfgData (void);
|
||||
/* Create and intialize a new CfgData struct, then return it. The function
|
||||
* uses the current output of the config scanner.
|
||||
*/
|
||||
|
||||
void FreeCfgData (CfgData* D);
|
||||
/* Free a config data structure */
|
||||
|
||||
void CfgDataCheckType (const CfgData* D, unsigned Type);
|
||||
/* Check the config data type and print an error message if it has the wrong
|
||||
* type.
|
||||
*/
|
||||
|
||||
int CfgDataFind (const Collection* Attributes, const char* AttrName);
|
||||
/* Find the attribute with the given name and return its index. Return -1 if
|
||||
* the attribute was not found.
|
||||
*/
|
||||
|
||||
int CfgDataGetId (Collection* Attributes, const char* Name, char** Id);
|
||||
/* Search CfgInfo for an attribute with the given name and type "id". If
|
||||
* found, remove it from the configuration, copy it into Buf and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
|
||||
int CfgDataGetStr (Collection* Attributes, const char* Name, char** S);
|
||||
/* Search CfgInfo for an attribute with the given name and type "string".
|
||||
* If found, remove it from the configuration, copy it into Buf and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
|
||||
int CfgDataGetNum (Collection* Attributes, const char* Name, long* Val);
|
||||
/* Search CfgInfo for an attribute with the given name and type "number".
|
||||
* If found, remove it from the configuration, copy it into Val and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of cfgdata.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
419
src/sim65/chip.c
419
src/sim65/chip.c
@ -1,419 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* chip.c */
|
||||
/* */
|
||||
/* Interface for the chip plugins */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "fname.h"
|
||||
#include "print.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "cfgdata.h"
|
||||
#include "chip.h"
|
||||
#include "chipdata.h"
|
||||
#include "cpucore.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int GetCfgId (void* CfgInfo, const char* Name, char** Id);
|
||||
/* Search CfgInfo for an attribute with the given name and type "id". If
|
||||
* found, remove it from the configuration, pass a pointer to a dynamically
|
||||
* allocated string containing the value to Id, and return true. If not
|
||||
* found, return false. The memory passed in Id must be free by a call to
|
||||
* Free();
|
||||
*/
|
||||
|
||||
static int GetCfgStr (void* CfgInfo, const char* Name, char** S);
|
||||
/* Search CfgInfo for an attribute with the given name and type "id". If
|
||||
* found, remove it from the configuration, pass a pointer to a dynamically
|
||||
* allocated string containing the value to Id, and return true. If not
|
||||
* found, return false. The memory passed in S must be free by a call to
|
||||
* Free();
|
||||
*/
|
||||
|
||||
static int GetCfgNum (void* CfgInfo, const char* Name, long* Val);
|
||||
/* Search CfgInfo for an attribute with the given name and type "number".
|
||||
* If found, remove it from the configuration, copy it into Val and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Sorted list of all chip data structures */
|
||||
static Collection Chips = STATIC_COLLECTION_INITIALIZER;
|
||||
|
||||
/* A collection containing all libraries */
|
||||
static Collection ChipLibraries = STATIC_COLLECTION_INITIALIZER;
|
||||
|
||||
/* SimData instance */
|
||||
static const SimData Sim65Data = {
|
||||
1, /* MajorVersion */
|
||||
1, /* MinorVersion */
|
||||
xmalloc,
|
||||
xfree,
|
||||
Warning,
|
||||
Error,
|
||||
Internal,
|
||||
GetCfgId,
|
||||
GetCfgStr,
|
||||
GetCfgNum,
|
||||
0,
|
||||
0,
|
||||
Break,
|
||||
IRQRequest,
|
||||
NMIRequest,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Helper functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int GetCfgId (void* CfgInfo, const char* Name, char** Id)
|
||||
/* Search CfgInfo for an attribute with the given name and type "id". If
|
||||
* found, remove it from the configuration, pass a pointer to a dynamically
|
||||
* allocated string containing the value to Id, and return true. If not
|
||||
* found, return false. The memory passed in Id must be free by a call to
|
||||
* Free();
|
||||
*/
|
||||
{
|
||||
return CfgDataGetId (CfgInfo, Name, Id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int GetCfgStr (void* CfgInfo, const char* Name, char** S)
|
||||
/* Search CfgInfo for an attribute with the given name and type "id". If
|
||||
* found, remove it from the configuration, pass a pointer to a dynamically
|
||||
* allocated string containing the value to Id, and return true. If not
|
||||
* found, return false. The memory passed in S must be free by a call to
|
||||
* Free();
|
||||
*/
|
||||
{
|
||||
return CfgDataGetStr (CfgInfo, Name, S);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int GetCfgNum (void* CfgInfo, const char* Name, long* Val)
|
||||
/* Search CfgInfo for an attribute with the given name and type "number".
|
||||
* If found, remove it from the configuration, copy it into Val and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
{
|
||||
return CfgDataGetNum (CfgInfo, Name, Val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int CmpChips (void* Data attribute ((unused)),
|
||||
const void* lhs, const void* rhs)
|
||||
/* Compare function for CollSort */
|
||||
{
|
||||
/* Cast the object pointers */
|
||||
const Chip* Left = (const Chip*) rhs;
|
||||
const Chip* Right = (const Chip*) lhs;
|
||||
|
||||
/* Do the compare */
|
||||
return strcmp (Left->Data->ChipName, Right->Data->ChipName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Chip* FindChip (const char* Name)
|
||||
/* Find a chip by name. Returns the Chip data structure or NULL if the chip
|
||||
* could not be found.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* ## We do a linear search for now */
|
||||
for (I = 0; I < CollCount (&Chips); ++I) {
|
||||
|
||||
/* Get the chip at this position */
|
||||
Chip* C = CollAt (&Chips, I);
|
||||
|
||||
/* Compare the name */
|
||||
if (strcmp (Name, C->Data->ChipName) == 0) {
|
||||
/* Found */
|
||||
return C;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static ChipLibrary* NewChipLibrary (const char* PathName)
|
||||
/* Create, initialize and return a new ChipLibrary structure */
|
||||
{
|
||||
/* Allocate memory */
|
||||
ChipLibrary* L = xmalloc (sizeof (ChipLibrary));
|
||||
|
||||
/* Initialize the fields */
|
||||
L->LibName = xstrdup (FindName (PathName));
|
||||
L->PathName = xstrdup (PathName);
|
||||
L->Handle = 0;
|
||||
L->Chips = EmptyCollection;
|
||||
|
||||
/* Return the allocated structure */
|
||||
return L;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void FreeChipLibrary (ChipLibrary* L)
|
||||
/* Free a ChipLibrary structure */
|
||||
{
|
||||
/* Free the names */
|
||||
xfree (L->LibName);
|
||||
xfree (L->PathName);
|
||||
|
||||
/* If the library is open, close it. Discard any errors. */
|
||||
if (L->Handle) {
|
||||
dlclose (L->Handle);
|
||||
(void) dlerror ();
|
||||
}
|
||||
|
||||
/* We may have to handle the Chip pointers, but currently the function
|
||||
* is never called with a non empty Chips collection, so we don't care
|
||||
* for now.
|
||||
*/
|
||||
xfree (L);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
|
||||
/* Allocate a new chip structure, initialize and return it */
|
||||
{
|
||||
/* Allocate memory */
|
||||
Chip* C = xmalloc (sizeof (Chip));
|
||||
|
||||
/* Initialize the fields */
|
||||
C->Lib = Library;
|
||||
C->Data = Data;
|
||||
C->Instances = EmptyCollection;
|
||||
|
||||
/* Insert the new chip into the collection of all chips */
|
||||
CollAppend (&Chips, C);
|
||||
|
||||
/* Return the structure */
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
|
||||
unsigned Size, Collection* Attributes)
|
||||
{
|
||||
ChipInstance* CI;
|
||||
|
||||
/* Find the chip with the given name */
|
||||
Chip* C = FindChip (ChipName);
|
||||
if (C == 0) {
|
||||
Error ("No chip `%s' found for address $%06X", ChipName, Addr);
|
||||
}
|
||||
|
||||
/* Allocate a new ChipInstance structure */
|
||||
CI = xmalloc (sizeof (*CI));
|
||||
|
||||
/* Initialize the fields */
|
||||
CI->C = C;
|
||||
CI->AS = 0;
|
||||
CI->Addr = Addr;
|
||||
CI->Size = Size;
|
||||
CI->Data = C->Data->CreateInstance (Addr, Size, Attributes);
|
||||
|
||||
/* Assign the chip instance to the chip */
|
||||
CollAppend (&C->Instances, CI);
|
||||
|
||||
/* Return the new instance struct */
|
||||
return CI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
|
||||
/* Generate a chip instance mirror and return it. */
|
||||
{
|
||||
/* Allocate a new ChipInstance structure */
|
||||
ChipInstance* CI = xmalloc (sizeof (*CI));
|
||||
|
||||
/* Initialize the fields */
|
||||
CI->C = Orig->C;
|
||||
CI->AS = 0;
|
||||
CI->Addr = Addr;
|
||||
CI->Size = Orig->Size;
|
||||
CI->Data = Orig->Data;
|
||||
|
||||
/* Assign the chip instance to the chip */
|
||||
CollAppend (&CI->C->Instances, CI);
|
||||
|
||||
/* Return the new instance struct */
|
||||
return CI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SortChips (void)
|
||||
/* Sort all chips by name. Called after loading */
|
||||
{
|
||||
/* Last act: Sort the chips by name */
|
||||
CollSort (&Chips, CmpChips, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LoadChipLibrary (const char* LibName)
|
||||
/* Load a chip library. This includes loading the shared libary, allocating
|
||||
* and initializing the data structure, and loading all chip data from the
|
||||
* library.
|
||||
*/
|
||||
{
|
||||
const char* Msg;
|
||||
int (*GetChipData) (const struct ChipData**, unsigned*);
|
||||
int ErrorCode;
|
||||
const ChipData* Data; /* Pointer to chip data */
|
||||
unsigned ChipCount; /* Number of chips in this library */
|
||||
unsigned I;
|
||||
|
||||
|
||||
/* Allocate a new ChipLibrary structure */
|
||||
ChipLibrary* L = NewChipLibrary (LibName);
|
||||
|
||||
/* Open the library */
|
||||
L->Handle = dlopen (L->PathName, RTLD_GLOBAL | RTLD_LAZY);
|
||||
|
||||
/* Check for errors */
|
||||
Msg = dlerror ();
|
||||
if (Msg) {
|
||||
Error ("Cannot open `%s': %s", L->PathName, Msg);
|
||||
FreeChipLibrary (L);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Locate the GetChipData function */
|
||||
GetChipData = dlsym (L->Handle, "GetChipData");
|
||||
|
||||
/* Check the error message */
|
||||
Msg = dlerror ();
|
||||
if (Msg) {
|
||||
/* We had an error */
|
||||
Error ("Cannot find export `GetChipData' in `%s': %s", L->LibName, Msg);
|
||||
FreeChipLibrary (L);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call the function to read the chip data */
|
||||
ErrorCode = GetChipData (&Data, &ChipCount);
|
||||
if (ErrorCode != 0) {
|
||||
Error ("Function `GetChipData' in `%s' returned error %d", L->LibName, ErrorCode);
|
||||
FreeChipLibrary (L);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remember the library */
|
||||
CollAppend (&ChipLibraries, L);
|
||||
|
||||
/* Print some information */
|
||||
Print (stderr, 1, "Opened chip library `%s'\n", L->PathName);
|
||||
|
||||
/* Create the chips */
|
||||
for (I = 0; I < ChipCount; ++I) {
|
||||
|
||||
Chip* C;
|
||||
|
||||
/* Get a pointer to the chip data */
|
||||
const ChipData* D = Data + I;
|
||||
|
||||
/* Check if the chip data has the correct version */
|
||||
if (D->MajorVersion != CHIPDATA_VER_MAJOR) {
|
||||
Warning ("Version mismatch for `%s' (%s), expected %u, got %u",
|
||||
D->ChipName, L->LibName,
|
||||
CHIPDATA_VER_MAJOR, D->MajorVersion);
|
||||
/* Ignore this chip */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Initialize the chip passing the simulator data */
|
||||
D->InitChip (&Sim65Data);
|
||||
|
||||
/* Generate a new chip */
|
||||
C = NewChip (L, D);
|
||||
|
||||
/* Insert a reference to the chip into the library exporting it */
|
||||
CollAppend (&L->Chips, C);
|
||||
|
||||
/* Output chip name and version to keep the user happy */
|
||||
Print (stdout, 1,
|
||||
" Found %s `%s', version %u.%u in library `%s'\n",
|
||||
(D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu",
|
||||
D->ChipName,
|
||||
D->MajorVersion,
|
||||
D->MinorVersion,
|
||||
L->LibName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
118
src/sim65/chip.h
118
src/sim65/chip.h
@ -1,118 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* chip.h */
|
||||
/* */
|
||||
/* Interface for the chip plugins */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CHIP_H
|
||||
#define CHIP_H
|
||||
|
||||
|
||||
|
||||
/* common.h */
|
||||
#include "coll.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chipdata.h"
|
||||
#include "simdata.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Forwards */
|
||||
struct AddressSpace;
|
||||
struct CfgData;
|
||||
typedef struct ChipInstance ChipInstance;
|
||||
typedef struct Chip Chip;
|
||||
typedef struct ChipLibrary ChipLibrary;
|
||||
|
||||
/* One instance of a chip */
|
||||
struct ChipInstance {
|
||||
Chip* C; /* Pointer to corresponding chip */
|
||||
struct AddressSpace* AS; /* Pointer to address space */
|
||||
unsigned Addr; /* Start address of range */
|
||||
unsigned Size; /* Size of range */
|
||||
void* Data; /* Chip instance data */
|
||||
};
|
||||
|
||||
/* Chip structure */
|
||||
struct Chip {
|
||||
struct ChipLibrary* Lib; /* Pointer to library data structure */
|
||||
const ChipData* Data; /* Chip data as given by the library */
|
||||
Collection Instances; /* Pointer to chip instances */
|
||||
};
|
||||
|
||||
/* ChipLibrary structure */
|
||||
struct ChipLibrary {
|
||||
char* LibName; /* Name of the library as given */
|
||||
char* PathName; /* Name of library including path */
|
||||
void* Handle; /* Pointer to libary handle */
|
||||
Collection Chips; /* Chips in this library */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
|
||||
unsigned Size, Collection* Attributes);
|
||||
/* Allocate a new chip instance for the chip. */
|
||||
|
||||
ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr);
|
||||
/* Generate a chip instance mirror and return it. */
|
||||
|
||||
void SortChips (void);
|
||||
/* Sort all chips by name. Called after loading */
|
||||
|
||||
void LoadChipLibrary (const char* LibName);
|
||||
/* Load a chip library. This includes loading the shared libary, allocating
|
||||
* and initializing the data structure, and loading all chip data from the
|
||||
* library.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of chip.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,82 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* chipdata.h */
|
||||
/* */
|
||||
/* Chip description data structure */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CHIPDATA_H
|
||||
#define CHIPDATA_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Chip type and version information. */
|
||||
#define CHIPDATA_TYPE_CHIP 0U
|
||||
#define CHIPDATA_TYPE_CPU 1U
|
||||
#define CHIPDATA_VER_MAJOR 1U
|
||||
#define CHIPDATA_VER_MINOR 0U
|
||||
|
||||
/* Forwards */
|
||||
struct CfgData;
|
||||
struct SimData;
|
||||
|
||||
/* ChipDesc structure */
|
||||
typedef struct ChipData ChipData;
|
||||
struct ChipData {
|
||||
const char* ChipName; /* Name of the chip */
|
||||
unsigned Type; /* Type of the chip */
|
||||
unsigned MajorVersion; /* Version information */
|
||||
unsigned MinorVersion;
|
||||
|
||||
/* -- Exported functions -- */
|
||||
int (*InitChip) (const struct SimData* Data);
|
||||
void* (*CreateInstance) (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
void (*DestroyInstance) (void* Data);
|
||||
void (*WriteCtrl) (void* Data, unsigned Offs, unsigned char Val);
|
||||
void (*Write) (void* Data, unsigned Offs, unsigned char Val);
|
||||
unsigned char (*ReadCtrl) (void* Data, unsigned Offs);
|
||||
unsigned char (*Read) (void* Data, unsigned Offs);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* End of chipdata.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,52 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* chipif.h */
|
||||
/* */
|
||||
/* Interface header file for chip plugins - unused by sim65 */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CHIPIF_H
|
||||
#define CHIPIF_H
|
||||
|
||||
|
||||
|
||||
/* sim65 */
|
||||
#include "chipdata.h"
|
||||
#include "simdata.h"
|
||||
|
||||
|
||||
|
||||
/* End of chipif.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,81 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* chippath.h */
|
||||
/* */
|
||||
/* Chip path handling for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2010, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if defined(_MSC_VER)
|
||||
/* Microsoft compiler */
|
||||
# include <io.h>
|
||||
#else
|
||||
/* Anyone else */
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* sim65 */
|
||||
#include "chippath.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
SearchPath* ChipSearchPath; /* Search paths for chip libs */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void InitChipPaths (void)
|
||||
/* Initialize the chip search path list */
|
||||
{
|
||||
/* Create the search path list */
|
||||
ChipSearchPath = NewSearchPath ();
|
||||
|
||||
/* Add the current directory to the search path */
|
||||
AddSearchPath (ChipSearchPath, "");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* chippath.h */
|
||||
/* */
|
||||
/* Chip path handling for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2010, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CHIPPATH_H
|
||||
#define CHIPPATH_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "searchpath.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
extern SearchPath* ChipSearchPath; /* Search paths for chip libs */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void InitChipPaths (void);
|
||||
/* Initialize the chip search path list */
|
||||
|
||||
|
||||
|
||||
/* End of chippath.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,659 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* console.c */
|
||||
/* */
|
||||
/* Console plugin for the sim65 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chipif.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int ScreenInitChip (const struct SimData* Data);
|
||||
/* Initialize the chip, return an error code */
|
||||
|
||||
static void* ScreenCreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
/* Create a new chip instance */
|
||||
|
||||
static void ScreenDestroyInstance (void* Data);
|
||||
/* Destroy a chip instance */
|
||||
|
||||
static void ScreenWrite (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write user data */
|
||||
|
||||
static unsigned char ScreenRead (void* Data, unsigned Offs);
|
||||
/* Read user data */
|
||||
|
||||
static void ScreenDrawBorder (void);
|
||||
/* Draw the complete border */
|
||||
|
||||
static void ScreenDrawChar (unsigned Offs);
|
||||
/* Draw one character at the given position */
|
||||
|
||||
static void ScreenDrawAllChars (void);
|
||||
/* Redraw the complete interior screen */
|
||||
|
||||
static void ScreenEventLoop (void);
|
||||
/* Get all waiting events and handle them */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Global data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* The SimData pointer we get when InitChip is called */
|
||||
static const SimData* Sim;
|
||||
|
||||
/* Control data passed to the main program */
|
||||
static const struct ChipData CData[] = {
|
||||
{
|
||||
"VIDEOSCREEN", /* Name of the chip */
|
||||
CHIPDATA_TYPE_CHIP, /* Type of the chip */
|
||||
CHIPDATA_VER_MAJOR, /* Version information */
|
||||
CHIPDATA_VER_MINOR,
|
||||
|
||||
/* -- Exported functions -- */
|
||||
ScreenInitChip,
|
||||
ScreenCreateInstance,
|
||||
ScreenDestroyInstance,
|
||||
ScreenWrite,
|
||||
ScreenWrite,
|
||||
ScreenRead,
|
||||
ScreenRead
|
||||
},
|
||||
};
|
||||
|
||||
/* Defines for console screen */
|
||||
static const XColor GreenColor = {
|
||||
0, 32*256, 141*256, 32*256, 0, 0 /* green */
|
||||
};
|
||||
static const XColor AmberColor = {
|
||||
0, 255*256, 204*256, 51*256, 0, 0 /* amber */
|
||||
};
|
||||
static const XColor WhiteColor = {
|
||||
0, 224*256, 224*256, 224*256, 0, 0 /* white */
|
||||
};
|
||||
static const XColor BgColor = {
|
||||
0, 0*256, 0*256, 0*256, 0, 0 /* black */
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Screen instance data */
|
||||
typedef struct ScreenInstance ScreenInstance;
|
||||
struct ScreenInstance {
|
||||
|
||||
/* Settings passed from the simulator */
|
||||
unsigned Addr; /* Address of the chip */
|
||||
unsigned Range; /* Memory range */
|
||||
|
||||
/* X variables */
|
||||
Display* ScreenDisplay;
|
||||
Window ScreenWindow;
|
||||
int Screen;
|
||||
GC ScreenGC;
|
||||
|
||||
/* Windows rows and columns */
|
||||
unsigned Rows;
|
||||
unsigned Cols;
|
||||
|
||||
/* Window dimensions, determined by char resolution and char set */
|
||||
unsigned XTotal;
|
||||
unsigned YTotal;
|
||||
|
||||
/* Usable area within the window */
|
||||
unsigned XSize;
|
||||
unsigned YSize;
|
||||
|
||||
/* Offset of the usable area */
|
||||
unsigned XOffs;
|
||||
unsigned YOffs;
|
||||
|
||||
/* Character height */
|
||||
unsigned CharHeight;
|
||||
|
||||
/* Fore- and background color */
|
||||
XColor FgColor;
|
||||
XColor BgColor;
|
||||
|
||||
/* A list of 4 rectangles used to draw the border */
|
||||
XRectangle Border[4];
|
||||
|
||||
/* The virtual screen we are writing to. */
|
||||
unsigned MemSize;
|
||||
unsigned char* Mem;
|
||||
|
||||
/* The font data */
|
||||
unsigned FontDataSize;
|
||||
unsigned char* FontData;
|
||||
|
||||
};
|
||||
|
||||
/* If we have a video ram window, place it's instance data here */
|
||||
static ScreenInstance* VScreen = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exported function */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int GetChipData (const ChipData** Data, unsigned* Count)
|
||||
{
|
||||
/* Pass the control structure to the caller */
|
||||
*Data = CData;
|
||||
*Count = sizeof (CData) / sizeof (CData[0]);
|
||||
|
||||
/* Call was successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Helper functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static long CfgGetNum (void* CfgInfo, const char* AttrName, long Min, long Max, long Def)
|
||||
/* Read a number from the attributes. Check against Min/Max. Return the
|
||||
* number or Def if it doesn't exist.
|
||||
*/
|
||||
{
|
||||
long Val;
|
||||
|
||||
/* Read the attribute if it does exist */
|
||||
if (Sim->GetCfgNum (CfgInfo, AttrName, &Val)) {
|
||||
/* Check it */
|
||||
if (Val < Min || Val > Max) {
|
||||
Sim->Error ("Range error for attribute `%s'", AttrName);
|
||||
}
|
||||
|
||||
/* Return it */
|
||||
return Val;
|
||||
|
||||
} else {
|
||||
|
||||
/* Return the default */
|
||||
return Def;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Console screen */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int ScreenInitChip (const struct SimData* Data)
|
||||
/* Initialize the chip, return an error code */
|
||||
{
|
||||
/* Remember the pointer */
|
||||
Sim = Data;
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void* ScreenCreateInstance (unsigned Addr, unsigned Range, void* CfgInfo)
|
||||
/* Create a new chip instance */
|
||||
{
|
||||
char* Name;
|
||||
FILE* F;
|
||||
unsigned ColorDepth;
|
||||
Colormap CM;
|
||||
XSizeHints SizeHints;
|
||||
XWMHints WMHints;
|
||||
Cursor C;
|
||||
unsigned CharColor;
|
||||
|
||||
|
||||
/* Allocate the instance data */
|
||||
ScreenInstance* V = VScreen = Sim->Malloc (sizeof (ScreenInstance));
|
||||
|
||||
/* Remember a few settings */
|
||||
V->Addr = Addr;
|
||||
V->Range = Range;
|
||||
|
||||
/* Character height is 8 or given as attribute */
|
||||
V->CharHeight = (unsigned) CfgGetNum (CfgInfo, "charheight", 8, 16, 8);
|
||||
|
||||
/* Allocate memory for the font */
|
||||
V->FontDataSize = V->CharHeight * 256;
|
||||
V->FontData = Sim->Malloc (V->FontDataSize);
|
||||
|
||||
/* We must have a "fontdata" attribute. Get it. */
|
||||
if (Sim->GetCfgStr (CfgInfo, "fontdata", &Name) == 0) {
|
||||
/* Attribute not found */
|
||||
Sim->Error ("Attribute `fontdata' missing"); /* ### */
|
||||
}
|
||||
|
||||
/* Open the file with the given name */
|
||||
F = fopen (Name, "rb");
|
||||
if (F == 0) {
|
||||
Sim->Error ("Cannot open `%s': %s", Name, strerror (errno));
|
||||
}
|
||||
|
||||
/* Read the file into the memory */
|
||||
if (fread (V->FontData, 1, V->FontDataSize, F) != V->FontDataSize) {
|
||||
Sim->Warning ("Font data file `%s' seems to be corrupt", Name);
|
||||
}
|
||||
|
||||
/* Close the file */
|
||||
fclose (F);
|
||||
|
||||
/* Free the file name */
|
||||
Sim->Free (Name);
|
||||
|
||||
/* Read screen rows and columns */
|
||||
V->Rows = (unsigned) CfgGetNum (CfgInfo, "rows", 15, 75, 25);
|
||||
V->Cols = (unsigned) CfgGetNum (CfgInfo, "cols", 32, 132, 80);
|
||||
|
||||
/* Allocate screen memory and clear it */
|
||||
V->MemSize = V->Rows * V->Cols;
|
||||
V->Mem = Sim->Malloc (V->MemSize);
|
||||
memset (V->Mem, ' ', V->MemSize);
|
||||
|
||||
/* Setup the window geometry */
|
||||
V->XSize = V->Cols * 8;
|
||||
V->YSize = V->Rows * V->CharHeight;
|
||||
V->XTotal = V->XSize + 20;
|
||||
V->YTotal = V->YSize + 20;
|
||||
V->XOffs = (V->XTotal - V->XSize) / 2;
|
||||
V->YOffs = (V->YTotal - V->YSize) / 2;
|
||||
|
||||
/* Setup the rectanges used to draw the exterior */
|
||||
V->Border[0].x = 0;
|
||||
V->Border[0].y = 0;
|
||||
V->Border[0].width = V->XTotal;
|
||||
V->Border[0].height = V->YOffs;
|
||||
V->Border[1].x = 0;
|
||||
V->Border[1].y = V->YOffs + V->YSize;
|
||||
V->Border[1].width = V->XTotal;
|
||||
V->Border[1].height = V->YOffs;
|
||||
V->Border[2].x = 0;
|
||||
V->Border[2].y = V->YOffs;
|
||||
V->Border[2].width = V->XOffs;
|
||||
V->Border[2].height = V->YSize;
|
||||
V->Border[3].x = V->XOffs + V->XSize;
|
||||
V->Border[3].y = V->YOffs;
|
||||
V->Border[3].width = V->XOffs;
|
||||
V->Border[3].height = V->YSize;
|
||||
|
||||
/* Open the X display. */
|
||||
V->ScreenDisplay = XOpenDisplay ("");
|
||||
if (V->ScreenDisplay == NULL) {
|
||||
Sim->Error ("Screen: Cannot open X display");
|
||||
}
|
||||
|
||||
/* Get a screen */
|
||||
V->Screen = DefaultScreen (V->ScreenDisplay);
|
||||
|
||||
/* Check the available colors. For now, we expect direct colors, so we
|
||||
* will check for a color depth of at least 16.
|
||||
*/
|
||||
ColorDepth = XDefaultDepth (V->ScreenDisplay, V->Screen);
|
||||
if (ColorDepth < 16) {
|
||||
/* OOPS */
|
||||
Sim->Error ("Screen: Need color display");
|
||||
}
|
||||
|
||||
/* Determine the character color */
|
||||
CharColor = (unsigned) CfgGetNum (CfgInfo, "charcolor", 0, 2, 0);
|
||||
|
||||
/* Get all needed colors */
|
||||
switch (CharColor) {
|
||||
case 1: V->FgColor = AmberColor; break;
|
||||
case 2: V->FgColor = WhiteColor; break;
|
||||
default: V->FgColor = GreenColor; break;
|
||||
}
|
||||
V->BgColor = BgColor;
|
||||
CM = DefaultColormap (V->ScreenDisplay, V->Screen);
|
||||
if (XAllocColor (V->ScreenDisplay, CM, &V->FgColor) == 0) {
|
||||
Sim->Error ("Screen: Cannot allocate foreground color");
|
||||
}
|
||||
if (XAllocColor (V->ScreenDisplay, CM, &V->BgColor) == 0) {
|
||||
Sim->Error ("Screen: Cannot allocate background color");
|
||||
}
|
||||
|
||||
/* Set up the size hints structure */
|
||||
SizeHints.x = 0;
|
||||
SizeHints.y = 0;
|
||||
SizeHints.flags = PPosition | PSize | PMinSize | PMaxSize | PResizeInc;
|
||||
SizeHints.width = V->XTotal;
|
||||
SizeHints.height = V->YTotal;
|
||||
SizeHints.min_width = V->XTotal;
|
||||
SizeHints.min_height = V->YTotal;
|
||||
SizeHints.max_width = V->XTotal;
|
||||
SizeHints.max_height = V->YTotal;
|
||||
SizeHints.width_inc = 0;
|
||||
SizeHints.height_inc = 0;
|
||||
WMHints.flags = InputHint;
|
||||
WMHints.input = True;
|
||||
|
||||
/* Create the window */
|
||||
V->ScreenWindow = XCreateSimpleWindow (V->ScreenDisplay,
|
||||
DefaultRootWindow (V->ScreenDisplay),
|
||||
SizeHints.x,
|
||||
SizeHints.y,
|
||||
SizeHints.width,
|
||||
SizeHints.height,
|
||||
5,
|
||||
V->FgColor.pixel,
|
||||
V->BgColor.pixel);
|
||||
|
||||
/* Set the standard window properties */
|
||||
XSetStandardProperties (V->ScreenDisplay, /* Display */
|
||||
V->ScreenWindow, /* Window */
|
||||
"sim65 console screen", /* Window name */
|
||||
"sim65 console screen", /* Icon name */
|
||||
None, /* Icon Pixmap */
|
||||
0, /* argv */
|
||||
0, /* argc */
|
||||
&SizeHints); /* Hints */
|
||||
XSetWMHints (V->ScreenDisplay, V->ScreenWindow, &WMHints);
|
||||
|
||||
/* GC creation and initialization */
|
||||
V->ScreenGC = XCreateGC (V->ScreenDisplay, V->ScreenWindow, 0, 0);
|
||||
|
||||
/* Set the cursor to show over the console window */
|
||||
C = XCreateFontCursor (V->ScreenDisplay, XC_pirate);
|
||||
XDefineCursor (V->ScreenDisplay, V->ScreenWindow, C);
|
||||
|
||||
/* Select input events */
|
||||
XSelectInput (V->ScreenDisplay, V->ScreenWindow, ExposureMask | StructureNotifyMask | KeyPressMask);
|
||||
|
||||
/* Show the window */
|
||||
XMapRaised (V->ScreenDisplay, V->ScreenWindow);
|
||||
|
||||
/* Handle events */
|
||||
ScreenEventLoop ();
|
||||
|
||||
/* Return the instance data */
|
||||
return V;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ScreenDestroyInstance (void* Data)
|
||||
/* Destroy a chip instance */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
ScreenInstance* V = Data;
|
||||
|
||||
/* Free X resources */
|
||||
XUndefineCursor (V->ScreenDisplay, V->ScreenWindow);
|
||||
XFreeGC (V->ScreenDisplay, V->ScreenGC);
|
||||
XDestroyWindow (V->ScreenDisplay, V->ScreenWindow);
|
||||
XCloseDisplay (V->ScreenDisplay);
|
||||
|
||||
/* Clear the global pointer */
|
||||
VScreen = 0;
|
||||
|
||||
/* Free the instance data */
|
||||
Sim->Free (V->FontData);
|
||||
Sim->Free (V->Mem);
|
||||
Sim->Free (V);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ScreenWrite (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
ScreenInstance* V = Data;
|
||||
|
||||
/* Check the offset */
|
||||
if (Offs >= V->MemSize) {
|
||||
Sim->Break ("Screen: Accessing invalid memory at $%06X", V->Addr + Offs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write the value */
|
||||
V->Mem[Offs] = Val;
|
||||
|
||||
/* Schedule a redraw */
|
||||
ScreenDrawChar (Offs);
|
||||
|
||||
/* Call the event loop */
|
||||
ScreenEventLoop ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char ScreenRead (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
ScreenInstance* V = Data;
|
||||
|
||||
/* Check the offset */
|
||||
if (Offs >= sizeof (V->Mem)) {
|
||||
Sim->Break ("Screen: Accessing invalid memory at $%06X", V->Addr + Offs);
|
||||
return 0xFF;
|
||||
} else {
|
||||
return V->Mem[Offs];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ScreenDrawBorder (void)
|
||||
/* Draw the complete border */
|
||||
{
|
||||
if (VScreen) {
|
||||
/* Set the border color */
|
||||
XSetForeground (VScreen->ScreenDisplay, VScreen->ScreenGC, VScreen->BgColor.pixel);
|
||||
|
||||
/* Fill all rectangles that make the border */
|
||||
XFillRectangles (VScreen->ScreenDisplay, VScreen->ScreenWindow, VScreen->ScreenGC,
|
||||
VScreen->Border, sizeof (VScreen->Border) / sizeof (VScreen->Border[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ScreenDrawChar (unsigned Offs)
|
||||
/* Draw one character at the given position */
|
||||
{
|
||||
unsigned Row, Col;
|
||||
XPoint Points[128];
|
||||
unsigned PCount;
|
||||
|
||||
/* Get the character from the video RAM */
|
||||
unsigned char C = VScreen->Mem[Offs];
|
||||
|
||||
/* Calculate the offset for the character data in the character ROM */
|
||||
unsigned char* D = VScreen->FontData + (C * VScreen->CharHeight);
|
||||
|
||||
/* Calculate the coords for the output */
|
||||
unsigned X = VScreen->XOffs + (Offs % VScreen->Cols) * 8;
|
||||
unsigned Y = VScreen->YOffs + (Offs / VScreen->Cols) * VScreen->CharHeight;
|
||||
|
||||
/* Clear the character area with the background color */
|
||||
XSetForeground (VScreen->ScreenDisplay, VScreen->ScreenGC, VScreen->BgColor.pixel);
|
||||
XFillRectangle (VScreen->ScreenDisplay, VScreen->ScreenWindow, VScreen->ScreenGC, X, Y, 8, VScreen->CharHeight);
|
||||
|
||||
/* Prepare the foreground pixels */
|
||||
PCount = 0;
|
||||
for (Row = 0; Row < VScreen->CharHeight; ++Row) {
|
||||
|
||||
/* Get next byte from char rom */
|
||||
unsigned Data = *D++;
|
||||
|
||||
/* Make pixels from this byte */
|
||||
for (Col = 0; Col < 8; ++Col) {
|
||||
if (Data & 0x80) {
|
||||
/* Foreground pixel */
|
||||
Points[PCount].x = X + Col;
|
||||
Points[PCount].y = Y + Row;
|
||||
++PCount;
|
||||
}
|
||||
Data <<= 1;
|
||||
}
|
||||
}
|
||||
if (PCount) {
|
||||
/* Set the character color */
|
||||
XSetForeground (VScreen->ScreenDisplay, VScreen->ScreenGC, VScreen->FgColor.pixel);
|
||||
|
||||
/* Draw the pixels */
|
||||
XDrawPoints (VScreen->ScreenDisplay, VScreen->ScreenWindow, VScreen->ScreenGC,
|
||||
Points, PCount, CoordModeOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ScreenDrawArea (unsigned X1, unsigned Y1, unsigned X2, unsigned Y2)
|
||||
/* Update an area of the interior screen */
|
||||
{
|
||||
unsigned X, Y;
|
||||
|
||||
/* Check if we have to draw anything */
|
||||
if (X2 < VScreen->XOffs || Y2 < VScreen->YOffs ||
|
||||
X1 >= VScreen->XOffs + VScreen->XSize ||
|
||||
Y1 >= VScreen->YOffs + VScreen->YSize) {
|
||||
/* Completely outside */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make the coordinates relative to the interior */
|
||||
X1 -= VScreen->XOffs;
|
||||
Y1 -= VScreen->YOffs;
|
||||
X2 -= VScreen->XOffs;
|
||||
Y2 -= VScreen->YOffs;
|
||||
|
||||
/* Loop updating characters */
|
||||
for (Y = Y1; Y <= Y2; Y += 8) {
|
||||
for (X = X1; X <= X2; X += 8) {
|
||||
ScreenDrawChar ((Y / 8) * 40 + (X / 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ScreenDrawAllChars (void)
|
||||
/* Redraw the complete interior screen */
|
||||
{
|
||||
unsigned I;
|
||||
for (I = 0; I < 25*40; ++I) {
|
||||
ScreenDrawChar (I);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ScreenEventLoop (void)
|
||||
/* Get all waiting events and handle them */
|
||||
{
|
||||
unsigned X1, Y1, X2, Y2;
|
||||
|
||||
/* Read input events */
|
||||
while (XEventsQueued (VScreen->ScreenDisplay, QueuedAfterFlush) != 0) {
|
||||
|
||||
/* Read an event */
|
||||
XEvent Event;
|
||||
XNextEvent (VScreen->ScreenDisplay, &Event);
|
||||
|
||||
switch (Event.type) {
|
||||
|
||||
case Expose:
|
||||
/* Calculate the area to redraw, then update the screen */
|
||||
X1 = Event.xexpose.x;
|
||||
Y1 = Event.xexpose.y;
|
||||
X2 = Event.xexpose.x + Event.xexpose.width - 1;
|
||||
Y2 = Event.xexpose.y + Event.xexpose.height - 1;
|
||||
if (X1 < VScreen->XOffs || X2 > VScreen->XOffs + VScreen->XSize ||
|
||||
Y1 < VScreen->YOffs || Y2 > VScreen->YOffs + VScreen->YSize) {
|
||||
/* Update the border */
|
||||
ScreenDrawBorder ();
|
||||
}
|
||||
ScreenDrawArea (X1, Y1, X2, Y2);
|
||||
break;
|
||||
|
||||
case MappingNotify:
|
||||
XRefreshKeyboardMapping (&Event.xmapping);
|
||||
break;
|
||||
|
||||
case KeyPress:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Ignore anything else */
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush the outgoing event queue */
|
||||
XFlush (VScreen->ScreenDisplay);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,266 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* ram.c */
|
||||
/* */
|
||||
/* RAM plugin for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* sim65 */
|
||||
#include "chipif.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int InitChip (const struct SimData* Data);
|
||||
/* Initialize the chip, return an error code */
|
||||
|
||||
static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
/* Create a new chip instance */
|
||||
|
||||
static void DestroyInstance (void* Data);
|
||||
/* Destroy a chip instance */
|
||||
|
||||
static void WriteCtrl (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write control data */
|
||||
|
||||
static void Write (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write user data */
|
||||
|
||||
static unsigned char ReadCtrl (void* Data, unsigned Offs);
|
||||
/* Read control data */
|
||||
|
||||
static unsigned char Read (void* Data, unsigned Offs);
|
||||
/* Read user data */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Control data passed to the main program */
|
||||
static const struct ChipData CData[1] = {
|
||||
{
|
||||
"RAM", /* Name of the chip */
|
||||
CHIPDATA_TYPE_CHIP, /* Type of the chip */
|
||||
CHIPDATA_VER_MAJOR, /* Version information */
|
||||
CHIPDATA_VER_MINOR,
|
||||
|
||||
/* -- Exported functions -- */
|
||||
InitChip,
|
||||
CreateInstance,
|
||||
DestroyInstance,
|
||||
WriteCtrl,
|
||||
Write,
|
||||
ReadCtrl,
|
||||
Read
|
||||
}
|
||||
};
|
||||
|
||||
/* The SimData pointer we get when InitChip is called */
|
||||
static const SimData* Sim;
|
||||
|
||||
/* Possible RAM attributes */
|
||||
#define ATTR_INITIALIZED 0x01 /* RAM cell is intialized */
|
||||
#define ATTR_WPROT 0x02 /* RAM cell is write protected */
|
||||
|
||||
/* Data for one RAM instance */
|
||||
typedef struct InstanceData InstanceData;
|
||||
struct InstanceData {
|
||||
unsigned BaseAddr; /* Base address */
|
||||
unsigned Range; /* Memory range */
|
||||
unsigned char* MemAttr; /* Memory attributes */
|
||||
unsigned char* Mem; /* The memory itself */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exported function */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int GetChipData (const ChipData** Data, unsigned* Count)
|
||||
{
|
||||
/* Pass the control structure to the caller */
|
||||
*Data = CData;
|
||||
*Count = sizeof (CData) / sizeof (CData[0]);
|
||||
|
||||
/* Call was successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int InitChip (const struct SimData* Data)
|
||||
/* Initialize the chip, return an error code */
|
||||
{
|
||||
/* Remember the pointer */
|
||||
Sim = Data;
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo)
|
||||
/* Create a new chip instance */
|
||||
{
|
||||
long Val;
|
||||
|
||||
/* Allocate a new instance structure */
|
||||
InstanceData* D = Sim->Malloc (sizeof (InstanceData));
|
||||
|
||||
/* Initialize the structure, allocate RAM and attribute memory */
|
||||
D->BaseAddr = Addr;
|
||||
D->Range = Range;
|
||||
D->MemAttr = Sim->Malloc (Range * sizeof (D->MemAttr[0]));
|
||||
D->Mem = Sim->Malloc (Range * sizeof (D->Mem[0]));
|
||||
|
||||
/* Check if a value is given that should be used to clear the RAM.
|
||||
* Otherwise use random values.
|
||||
*/
|
||||
if (Sim->GetCfgNum (CfgInfo, "fill", &Val) == 0) {
|
||||
/* No "fill" attribute */
|
||||
unsigned I;
|
||||
for (I = 0; I < Range; ++I) {
|
||||
D->Mem[I] = (unsigned char) rand ();
|
||||
}
|
||||
} else {
|
||||
/* Got a "fill" attribute */
|
||||
memset (D->Mem, (int) Val, Range);
|
||||
}
|
||||
|
||||
/* Clear the attribute memory */
|
||||
memset (D->MemAttr, 0, Range * sizeof (D->MemAttr[0]));
|
||||
|
||||
/* Done, return the instance data */
|
||||
return D;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DestroyInstance (void* Data)
|
||||
/* Destroy a chip instance */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Free memory and attributes */
|
||||
Sim->Free (D->Mem);
|
||||
Sim->Free (D->MemAttr);
|
||||
|
||||
/* Free the instance data itself */
|
||||
free (D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void WriteCtrl (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write control data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Do the write and remember the cell as initialized */
|
||||
D->Mem[Offs] = Val;
|
||||
D->MemAttr[Offs] |= ATTR_INITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Write (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Check for a write to a write protected cell */
|
||||
if (D->MemAttr[Offs] & ATTR_WPROT) {
|
||||
Sim->Break ("Writing to write protected memory at $%04X", D->BaseAddr+Offs);
|
||||
}
|
||||
|
||||
/* Do the write and remember the cell as initialized */
|
||||
D->Mem[Offs] = Val;
|
||||
D->MemAttr[Offs] |= ATTR_INITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char ReadCtrl (void* Data, unsigned Offs)
|
||||
/* Read control data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Read the cell and return the value */
|
||||
return D->Mem[Offs];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char Read (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Check for a read from an uninitialized cell */
|
||||
if ((D->MemAttr[Offs] & ATTR_INITIALIZED) == 0) {
|
||||
/* We're reading a memory cell that was never written to */
|
||||
Sim->Break ("Reading from uninitialized memory at $%04X", D->BaseAddr+Offs);
|
||||
}
|
||||
|
||||
/* Read the cell and return the value */
|
||||
return D->Mem[Offs];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,255 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* rom.c */
|
||||
/* */
|
||||
/* ROM plugin for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* sim65 */
|
||||
#include "chipif.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int InitChip (const struct SimData* Data);
|
||||
/* Initialize the chip, return an error code */
|
||||
|
||||
static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
/* Create a new chip instance */
|
||||
|
||||
static void DestroyInstance (void* Data);
|
||||
/* Destroy a chip instance */
|
||||
|
||||
static void WriteCtrl (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write control data */
|
||||
|
||||
static void Write (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write user data */
|
||||
|
||||
static unsigned char ReadCtrl (void* Data, unsigned Offs);
|
||||
/* Read control data */
|
||||
|
||||
static unsigned char Read (void* Data, unsigned Offs);
|
||||
/* Read user data */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Control data passed to the main program */
|
||||
static const struct ChipData CData[1] = {
|
||||
{
|
||||
"ROM", /* Name of the chip */
|
||||
CHIPDATA_TYPE_CHIP, /* Type of the chip */
|
||||
CHIPDATA_VER_MAJOR, /* Version information */
|
||||
CHIPDATA_VER_MINOR,
|
||||
|
||||
/* -- Exported functions -- */
|
||||
InitChip,
|
||||
CreateInstance,
|
||||
DestroyInstance,
|
||||
WriteCtrl,
|
||||
Write,
|
||||
ReadCtrl,
|
||||
Read
|
||||
}
|
||||
};
|
||||
|
||||
/* The SimData pointer we get when InitChip is called */
|
||||
static const SimData* Sim;
|
||||
|
||||
/* Data for one ROM instance */
|
||||
typedef struct InstanceData InstanceData;
|
||||
struct InstanceData {
|
||||
unsigned BaseAddr; /* Base address */
|
||||
unsigned Range; /* Memory range */
|
||||
unsigned char* Mem; /* The memory itself */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exported function */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int GetChipData (const ChipData** Data, unsigned* Count)
|
||||
{
|
||||
/* Pass the control structure to the caller */
|
||||
*Data = CData;
|
||||
*Count = sizeof (CData) / sizeof (CData[0]);
|
||||
|
||||
/* Call was successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int InitChip (const struct SimData* Data)
|
||||
/* Initialize the chip, return an error code */
|
||||
{
|
||||
/* Remember the pointer */
|
||||
Sim = Data;
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo)
|
||||
/* Create a new chip instance */
|
||||
{
|
||||
char* Name;
|
||||
FILE* F;
|
||||
|
||||
/* Allocate a new instance structure */
|
||||
InstanceData* D = Sim->Malloc (sizeof (InstanceData));
|
||||
|
||||
/* Initialize the structure, allocate RAM and attribute memory */
|
||||
D->BaseAddr = Addr;
|
||||
D->Range = Range;
|
||||
D->Mem = Sim->Malloc (Range);
|
||||
|
||||
/* We must have a "file" attribute. Get it. */
|
||||
if (Sim->GetCfgStr (CfgInfo, "file", &Name) == 0) {
|
||||
/* Attribute not found */
|
||||
Sim->Error ("Attribute `file' missing"); /* ### */
|
||||
}
|
||||
|
||||
/* Open the file with the given name */
|
||||
F = fopen (Name, "rb");
|
||||
if (F == 0) {
|
||||
Sim->Error ("Cannot open `%s': %s", Name, strerror (errno));
|
||||
}
|
||||
|
||||
/* Read the file into the memory */
|
||||
if (fread (D->Mem, 1, D->Range, F) != D->Range) {
|
||||
Sim->Warning ("Cannot read %u bytes from file `%s'", D->Range, Name);
|
||||
}
|
||||
|
||||
/* Close the file */
|
||||
fclose (F);
|
||||
|
||||
/* Free the file name */
|
||||
Sim->Free (Name);
|
||||
|
||||
/* Done, return the instance data */
|
||||
return D;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DestroyInstance (void* Data)
|
||||
/* Destroy a chip instance */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Free the ROM memory */
|
||||
Sim->Free (D->Mem);
|
||||
|
||||
/* Free the instance data itself */
|
||||
free (D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void WriteCtrl (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write control data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Do the write */
|
||||
D->Mem[Offs] = Val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Write (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Print a warning */
|
||||
Sim->Break ("Writing to write protected memory at $%04X (value = $%02X)",
|
||||
D->BaseAddr+Offs, Val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char ReadCtrl (void* Data, unsigned Offs)
|
||||
/* Read control data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Read the cell and return the value */
|
||||
return D->Mem[Offs];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char Read (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
InstanceData* D = (InstanceData*) Data;
|
||||
|
||||
/* Read the cell and return the value */
|
||||
return D->Mem[Offs];
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,289 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* stdio.c */
|
||||
/* */
|
||||
/* STDIO plugin for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chipif.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int InitChip (const struct SimData* Data);
|
||||
/* Initialize the chip, return an error code */
|
||||
|
||||
static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
/* Create a new chip instance */
|
||||
|
||||
static void DestroyInstance (void* Data);
|
||||
/* Destroy a chip instance */
|
||||
|
||||
static void WriteCtrl (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write control data */
|
||||
|
||||
static void Write (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write user data */
|
||||
|
||||
static unsigned char ReadCtrl (void* Data, unsigned Offs);
|
||||
/* Read control data */
|
||||
|
||||
static unsigned char Read (void* Data, unsigned Offs);
|
||||
/* Read user data */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* The SimData pointer we get when InitChip is called */
|
||||
static const SimData* Sim;
|
||||
|
||||
/* Control data passed to the main program */
|
||||
static const struct ChipData CData[1] = {
|
||||
{
|
||||
"STDIO", /* Name of the chip */
|
||||
CHIPDATA_TYPE_CHIP, /* Type of the chip */
|
||||
CHIPDATA_VER_MAJOR, /* Version information */
|
||||
CHIPDATA_VER_MINOR,
|
||||
|
||||
/* -- Exported functions -- */
|
||||
InitChip,
|
||||
CreateInstance,
|
||||
DestroyInstance,
|
||||
WriteCtrl,
|
||||
Write,
|
||||
ReadCtrl,
|
||||
Read
|
||||
}
|
||||
};
|
||||
|
||||
/* Screen instance data */
|
||||
typedef struct InstanceData InstanceData;
|
||||
struct InstanceData {
|
||||
/* The memory area used for data */
|
||||
unsigned char* Mem[32];
|
||||
};
|
||||
|
||||
/* Function opcodes */
|
||||
enum {
|
||||
F_open,
|
||||
F_close,
|
||||
F_write,
|
||||
F_read,
|
||||
F_lseek,
|
||||
F_unlink,
|
||||
F_chdir,
|
||||
F_getcwd,
|
||||
F_mkdir,
|
||||
F_rmdir,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exported function */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int GetChipData (const ChipData** Data, unsigned* Count)
|
||||
{
|
||||
/* Pass the control structure to the caller */
|
||||
*Data = CData;
|
||||
*Count = sizeof (CData) / sizeof (CData[0]);
|
||||
|
||||
/* Call was successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int InitChip (const struct SimData* Data)
|
||||
/* Initialize the chip, return an error code */
|
||||
{
|
||||
/* Remember the pointer */
|
||||
Sim = Data;
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo)
|
||||
/* Initialize a new chip instance */
|
||||
{
|
||||
/* Allocate the instance data */
|
||||
InstanceData* D = Sim->Malloc (sizeof (InstanceData));
|
||||
|
||||
/* Initialize the instance data */
|
||||
memset (D->Mem, 0x00, sizeof (D->Mem));
|
||||
|
||||
/* Return the instance data */
|
||||
return D;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DestroyInstance (void* Data)
|
||||
/* Destroy a chip instance */
|
||||
{
|
||||
/* Cast the instance data pointer */
|
||||
InstanceData* D = Data;
|
||||
|
||||
/* Free the instance data */
|
||||
Sim->Free (D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void WriteCtrl (void* Data attribute, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the instance data pointer */
|
||||
InstanceData* D = Data;
|
||||
|
||||
/* Write to the memory */
|
||||
D->Mem[Offs] = Val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Write (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the instance data pointer */
|
||||
InstanceData* D = Data;
|
||||
|
||||
/* Write to the memory */
|
||||
D->Mem[Offs] = Val;
|
||||
|
||||
/* Now check the offset. Zero is special because it will trigger the
|
||||
* action
|
||||
*/
|
||||
if (Offs == 0) {
|
||||
|
||||
/* The action is determined by the value that is written */
|
||||
switch (Val) {
|
||||
|
||||
case F_open:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_close:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_write:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_read:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_lseek:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_unlink:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_chdir:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_getcwd:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_mkdir:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
case F_rmdir:
|
||||
Sim->Break ("Unsupported function $%02X", Val);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char ReadCtrl (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the instance data pointer */
|
||||
InstanceData* D = Data;
|
||||
|
||||
/* Read the cell and return the value */
|
||||
return D->Mem[Offs];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char Read (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the instance data pointer */
|
||||
InstanceData* D = Data;
|
||||
|
||||
/* Read the cell and return the value */
|
||||
return D->Mem[Offs];
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,897 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* vic2.c */
|
||||
/* */
|
||||
/* VIC II plugin for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chipif.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int VicInitChip (const struct SimData* Data);
|
||||
/* Initialize the chip, return an error code */
|
||||
|
||||
static void* VicCreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
/* Create a new chip instance */
|
||||
|
||||
static void VicDestroyInstance (void* Data);
|
||||
/* Destroy a chip instance */
|
||||
|
||||
static void VicWrite (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write user data */
|
||||
|
||||
static unsigned char VicRead (void* Data, unsigned Offs);
|
||||
/* Read user data */
|
||||
|
||||
static int VRamInitChip (const struct SimData* Data);
|
||||
/* Initialize the chip, return an error code */
|
||||
|
||||
static void* VRamCreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
/* Create a new chip instance */
|
||||
|
||||
static void VRamDestroyInstance (void* Data);
|
||||
/* Destroy a chip instance */
|
||||
|
||||
static void VRamWrite (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write user data */
|
||||
|
||||
static unsigned char VRamRead (void* Data, unsigned Offs);
|
||||
/* Read user data */
|
||||
|
||||
static void VRamDrawBorder (void);
|
||||
/* Draw the complete border */
|
||||
|
||||
static void VRamDrawChar (unsigned Offs);
|
||||
/* Draw one character at the given position */
|
||||
|
||||
static void VRamDrawAllChars (void);
|
||||
/* Redraw the complete interior screen */
|
||||
|
||||
static void VRamEventLoop (void);
|
||||
/* Get all waiting events and handle them */
|
||||
|
||||
static int CRamInitChip (const struct SimData* Data);
|
||||
/* Initialize the chip, return an error code */
|
||||
|
||||
static void* CRamCreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
|
||||
/* Create a new chip instance */
|
||||
|
||||
static void CRamDestroyInstance (void* Data);
|
||||
/* Destroy a chip instance */
|
||||
|
||||
static void CRamWrite (void* Data, unsigned Offs, unsigned char Val);
|
||||
/* Write user data */
|
||||
|
||||
static unsigned char CRamRead (void* Data, unsigned Offs);
|
||||
/* Read user data */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Global data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* The SimData pointer we get when InitChip is called */
|
||||
static const SimData* Sim;
|
||||
|
||||
/* Control data passed to the main program */
|
||||
static const struct ChipData CData[] = {
|
||||
{
|
||||
"VIC2", /* Name of the chip */
|
||||
CHIPDATA_TYPE_CHIP, /* Type of the chip */
|
||||
CHIPDATA_VER_MAJOR, /* Version information */
|
||||
CHIPDATA_VER_MINOR,
|
||||
|
||||
/* -- Exported functions -- */
|
||||
VicInitChip,
|
||||
VicCreateInstance,
|
||||
VicDestroyInstance,
|
||||
VicWrite,
|
||||
VicWrite,
|
||||
VicRead,
|
||||
VicRead
|
||||
},
|
||||
{
|
||||
"VIC2-VIDEORAM", /* Name of the chip */
|
||||
CHIPDATA_TYPE_CHIP, /* Type of the chip */
|
||||
CHIPDATA_VER_MAJOR, /* Version information */
|
||||
CHIPDATA_VER_MINOR,
|
||||
|
||||
/* -- Exported functions -- */
|
||||
VRamInitChip,
|
||||
VRamCreateInstance,
|
||||
VRamDestroyInstance,
|
||||
VRamWrite,
|
||||
VRamWrite,
|
||||
VRamRead,
|
||||
VRamRead
|
||||
},
|
||||
{
|
||||
"VIC2-COLORRAM", /* Name of the chip */
|
||||
CHIPDATA_TYPE_CHIP, /* Type of the chip */
|
||||
CHIPDATA_VER_MAJOR, /* Version information */
|
||||
CHIPDATA_VER_MINOR,
|
||||
|
||||
/* -- Exported functions -- */
|
||||
CRamInitChip,
|
||||
CRamCreateInstance,
|
||||
CRamDestroyInstance,
|
||||
CRamWrite,
|
||||
CRamWrite,
|
||||
CRamRead,
|
||||
CRamRead
|
||||
}
|
||||
};
|
||||
|
||||
/* Defines for the VIC chip */
|
||||
#define VIC_COLOR_COUNT 16
|
||||
#define VIC_BLACK 0
|
||||
#define VIC_WHITE 1
|
||||
|
||||
/* The application color map. VIC II color values are taken from
|
||||
* http://www.pepto.de/projects/colorvic/ (Philip "Pepto" Timmermann)
|
||||
*/
|
||||
static XColor VicColors [VIC_COLOR_COUNT] = {
|
||||
{ 0, 0*256, 0*256, 0*256, 0, 0 }, /* black */
|
||||
{ 0, 255*256, 255*256, 255*256, 0, 0 }, /* white */
|
||||
{ 0, 104*256, 55*256, 43*256, 0, 0 }, /* red */
|
||||
{ 0, 112*256, 163*256, 178*256, 0, 0 }, /* cyan */
|
||||
{ 0, 111*256, 61*256, 134*256, 0, 0 }, /* purple */
|
||||
{ 0, 88*256, 141*256, 67*256, 0, 0 }, /* green */
|
||||
{ 0, 53*256, 40*256, 121*256, 0, 0 }, /* blue */
|
||||
{ 0, 184*256, 199*256, 111*256, 0, 0 }, /* yellow */
|
||||
{ 0, 111*256, 79*256, 37*256, 0, 0 }, /* orange */
|
||||
{ 0, 67*256, 57*256, 0*256, 0, 0 }, /* brown */
|
||||
{ 0, 154*256, 103*256, 89*256, 0, 0 }, /* light red */
|
||||
{ 0, 68*256, 68*256, 68*256, 0, 0 }, /* dark grey */
|
||||
{ 0, 108*256, 108*256, 108*256, 0, 0 }, /* grey */
|
||||
{ 0, 154*256, 210*256, 132*256, 0, 0 }, /* light green */
|
||||
{ 0, 108*256, 94*256, 181*256, 0, 0 }, /* light blue */
|
||||
{ 0, 149*256, 149*256, 149*256, 0, 0 } /* light grey */
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* VIC II instance data */
|
||||
typedef struct VicInstance VicInstance;
|
||||
struct VicInstance {
|
||||
unsigned Addr; /* Address of the chip */
|
||||
unsigned Range; /* Memory range */
|
||||
unsigned char Regs[47]; /* VIC registers */
|
||||
};
|
||||
|
||||
/* Video RAM instance data */
|
||||
typedef struct VRamInstance VRamInstance;
|
||||
struct VRamInstance {
|
||||
|
||||
/* Settings passed from the simulator */
|
||||
unsigned Addr; /* Address of the chip */
|
||||
unsigned Range; /* Memory range */
|
||||
|
||||
/* X variables */
|
||||
Display* VicDisplay;
|
||||
Window VicWindow;
|
||||
int VicScreen;
|
||||
GC VicGC;
|
||||
|
||||
/* Window dimensions, 384*288 (PAL) */
|
||||
unsigned XTotal;
|
||||
unsigned YTotal;
|
||||
|
||||
/* Usable area within the window */
|
||||
unsigned XSize;
|
||||
unsigned YSize;
|
||||
|
||||
/* Offset of the usable area */
|
||||
unsigned XOffs;
|
||||
unsigned YOffs;
|
||||
|
||||
/* The window color map. */
|
||||
XColor Colors [VIC_COLOR_COUNT];
|
||||
|
||||
/* A list of 4 rectangles used to draw the border */
|
||||
XRectangle Border[4];
|
||||
|
||||
/* The virtual screen we are writing to. */
|
||||
unsigned char Mem[0x400];
|
||||
|
||||
/* The character ROM data */
|
||||
unsigned char CharRom[0x1000];
|
||||
|
||||
};
|
||||
|
||||
typedef struct CRamInstance CRamInstance;
|
||||
struct CRamInstance {
|
||||
|
||||
/* Settings passed from the simulator */
|
||||
unsigned Addr; /* Address of the chip */
|
||||
unsigned Range; /* Memory range */
|
||||
|
||||
/* The memory we are writing to. */
|
||||
unsigned char Mem[0x400];
|
||||
};
|
||||
|
||||
/* If we have a video ram window, place it's instance data here */
|
||||
static VicInstance* Vic = 0;
|
||||
static VRamInstance* VRam = 0;
|
||||
static CRamInstance* CRam = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exported function */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int GetChipData (const ChipData** Data, unsigned* Count)
|
||||
{
|
||||
/* Pass the control structure to the caller */
|
||||
*Data = CData;
|
||||
*Count = sizeof (CData) / sizeof (CData[0]);
|
||||
|
||||
/* Call was successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* VIC II Chip */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int VicInitChip (const struct SimData* Data)
|
||||
/* Initialize the chip, return an error code */
|
||||
{
|
||||
/* Remember the pointer */
|
||||
Sim = Data;
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void* VicCreateInstance (unsigned Addr, unsigned Range,
|
||||
void* CfgInfo attribute ((unused)))
|
||||
/* Initialize a new chip instance */
|
||||
{
|
||||
/* Allocate a new instance structure */
|
||||
VicInstance* V = Vic = Sim->Malloc (sizeof (VicInstance));
|
||||
|
||||
/* Initialize the structure, allocate RAM and attribute memory */
|
||||
V->Addr = Addr;
|
||||
V->Range = Range;
|
||||
memset (V->Regs, 0, sizeof (V->Regs));
|
||||
|
||||
/* Done, return the instance data */
|
||||
return V;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VicDestroyInstance (void* Data)
|
||||
/* Destroy a chip instance */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
VicInstance* V = Data;
|
||||
|
||||
/* Free the instance data */
|
||||
Sim->Free (V);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VicWrite (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
VicInstance* V = Data;
|
||||
|
||||
/* Check for a write outside our range */
|
||||
if (Offs >= sizeof (V->Regs)) {
|
||||
Sim->Break ("Writing to invalid VIC register at $%04X", V->Addr+Offs);
|
||||
} else {
|
||||
|
||||
/* Do the write */
|
||||
V->Regs[Offs] = Val;
|
||||
|
||||
/* Handle special registers */
|
||||
switch (Offs) {
|
||||
case 32:
|
||||
/* Exterior color */
|
||||
if (VRam) {
|
||||
VRamDrawBorder ();
|
||||
}
|
||||
break;
|
||||
case 33:
|
||||
/* Background color #0 */
|
||||
if (VRam) {
|
||||
VRamDrawAllChars ();
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* Handle the event queue */
|
||||
if (VRam) {
|
||||
VRamEventLoop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char VicRead (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
VicInstance* V = Data;
|
||||
|
||||
/* Simulate the rasterline register */
|
||||
if (V->Regs[17] & 0x80) {
|
||||
if (++V->Regs[18] == (312 & 0xFF)) {
|
||||
V->Regs[17] &= 0x7F;
|
||||
V->Regs[18] = 0;
|
||||
}
|
||||
} else {
|
||||
if (++V->Regs[18] == 0) {
|
||||
V->Regs[17] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for a read outside our range */
|
||||
if (Offs >= sizeof (V->Regs)) {
|
||||
|
||||
Sim->Break ("Reading invalid VIC register at $%04X", V->Addr+Offs);
|
||||
return 0xFF;
|
||||
|
||||
} else {
|
||||
|
||||
/* Do the read */
|
||||
return V->Regs[Offs];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Video RAM */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int VRamInitChip (const struct SimData* Data)
|
||||
/* Initialize the chip, return an error code */
|
||||
{
|
||||
/* Remember the pointer */
|
||||
Sim = Data;
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void* VRamCreateInstance (unsigned Addr, unsigned Range, void* CfgInfo)
|
||||
/* Create a new chip instance */
|
||||
{
|
||||
char* Name;
|
||||
FILE* F;
|
||||
unsigned ColorDepth;
|
||||
Colormap CM;
|
||||
unsigned CIdx;
|
||||
XSizeHints SizeHints;
|
||||
XWMHints WMHints;
|
||||
Cursor C;
|
||||
|
||||
/* Allocate the instance data */
|
||||
VRamInstance* V = VRam = Sim->Malloc (sizeof (VRamInstance));
|
||||
|
||||
/* Remember a few settings */
|
||||
V->Addr = Addr;
|
||||
V->Range = Range;
|
||||
|
||||
/* Setup the window geometry */
|
||||
V->XTotal = 384; /* PAL */
|
||||
V->YTotal = 288;
|
||||
V->XSize = 320;
|
||||
V->YSize = 200;
|
||||
V->XOffs = (V->XTotal - V->XSize) / 2;
|
||||
V->YOffs = (V->YTotal - V->YSize) / 2;
|
||||
|
||||
/* Setup the rectanges used to draw the exterior */
|
||||
V->Border[0].x = 0;
|
||||
V->Border[0].y = 0;
|
||||
V->Border[0].width = V->XTotal;
|
||||
V->Border[0].height = V->YOffs;
|
||||
V->Border[1].x = 0;
|
||||
V->Border[1].y = V->YOffs + V->YSize;
|
||||
V->Border[1].width = V->XTotal;
|
||||
V->Border[1].height = V->YOffs;
|
||||
V->Border[2].x = 0;
|
||||
V->Border[2].y = V->YOffs;
|
||||
V->Border[2].width = V->XOffs;
|
||||
V->Border[2].height = V->YSize;
|
||||
V->Border[3].x = V->XOffs + V->XSize;
|
||||
V->Border[3].y = V->YOffs;
|
||||
V->Border[3].width = V->XOffs;
|
||||
V->Border[3].height = V->YSize;
|
||||
|
||||
/* We must have a "file" attribute. Get it. */
|
||||
if (Sim->GetCfgStr (CfgInfo, "file", &Name) == 0) {
|
||||
/* Attribute not found */
|
||||
Sim->Error ("Attribute `file' missing"); /* ### */
|
||||
}
|
||||
|
||||
/* Open the file with the given name */
|
||||
F = fopen (Name, "rb");
|
||||
if (F == 0) {
|
||||
Sim->Error ("Cannot open `%s': %s", Name, strerror (errno));
|
||||
}
|
||||
|
||||
/* Read the file into the memory */
|
||||
if (fread (V->CharRom, 1, sizeof (V->CharRom), F) != sizeof (V->CharRom)) {
|
||||
Sim->Warning ("Char ROM `%s' seems to be corrupt", Name);
|
||||
}
|
||||
|
||||
/* Close the file */
|
||||
fclose (F);
|
||||
|
||||
/* Free the file name */
|
||||
Sim->Free (Name);
|
||||
|
||||
/* Open the X display. */
|
||||
V->VicDisplay = XOpenDisplay ("");
|
||||
if (V->VicDisplay == NULL) {
|
||||
Sim->Error ("VRAM: Cannot open X display");
|
||||
}
|
||||
|
||||
/* Get a screen */
|
||||
V->VicScreen = DefaultScreen (V->VicDisplay);
|
||||
|
||||
/* Check the available colors. For now, we expect direct colors, so we
|
||||
* will check for a color depth of at least 16.
|
||||
*/
|
||||
ColorDepth = XDefaultDepth (V->VicDisplay, V->VicScreen);
|
||||
if (ColorDepth < 16) {
|
||||
/* OOPS */
|
||||
Sim->Error ("VRAM: Need color display");
|
||||
}
|
||||
|
||||
/* Get all needed colors */
|
||||
memcpy (V->Colors, VicColors, sizeof (V->Colors));
|
||||
CM = DefaultColormap (V->VicDisplay, V->VicScreen);
|
||||
for (CIdx = 0; CIdx < VIC_COLOR_COUNT; CIdx++) {
|
||||
if (XAllocColor (V->VicDisplay, CM, &V->Colors [CIdx]) == 0) {
|
||||
Sim->Error ("VRAM: Cannot allocate color");
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the size hints structure */
|
||||
SizeHints.x = 0;
|
||||
SizeHints.y = 0;
|
||||
SizeHints.flags = PPosition | PSize | PMinSize | PMaxSize | PResizeInc;
|
||||
SizeHints.width = V->XTotal;
|
||||
SizeHints.height = V->YTotal;
|
||||
SizeHints.min_width = V->XTotal;
|
||||
SizeHints.min_height = V->YTotal;
|
||||
SizeHints.max_width = V->XTotal;
|
||||
SizeHints.max_height = V->YTotal;
|
||||
SizeHints.width_inc = 0;
|
||||
SizeHints.height_inc = 0;
|
||||
WMHints.flags = InputHint;
|
||||
WMHints.input = True;
|
||||
|
||||
/* Create the window */
|
||||
V->VicWindow = XCreateSimpleWindow (V->VicDisplay,
|
||||
DefaultRootWindow (V->VicDisplay),
|
||||
SizeHints.x,
|
||||
SizeHints.y,
|
||||
SizeHints.width,
|
||||
SizeHints.height,
|
||||
5,
|
||||
V->Colors [VIC_WHITE].pixel,
|
||||
V->Colors [VIC_BLACK].pixel);
|
||||
|
||||
/* Set the standard window properties */
|
||||
XSetStandardProperties (V->VicDisplay, /* Display */
|
||||
V->VicWindow, /* Window */
|
||||
"sim65 VIC screen", /* Window name */
|
||||
"sim65 VIC screen", /* Icon name */
|
||||
None, /* Icon Pixmap */
|
||||
0, /* argv */
|
||||
0, /* argc */
|
||||
&SizeHints); /* Hints */
|
||||
XSetWMHints (V->VicDisplay, V->VicWindow, &WMHints);
|
||||
|
||||
/* GC creation and initialization */
|
||||
V->VicGC = XCreateGC (V->VicDisplay, V->VicWindow, 0, 0);
|
||||
|
||||
/* Set the cursor to show over the Vic window */
|
||||
C = XCreateFontCursor (V->VicDisplay, XC_pirate);
|
||||
XDefineCursor (V->VicDisplay, V->VicWindow, C);
|
||||
|
||||
/* Select input events */
|
||||
XSelectInput (V->VicDisplay, V->VicWindow, ExposureMask | StructureNotifyMask);
|
||||
|
||||
/* Show the window */
|
||||
XMapRaised (V->VicDisplay, V->VicWindow);
|
||||
|
||||
/* Handle events */
|
||||
VRamEventLoop ();
|
||||
|
||||
/* Return the instance data */
|
||||
return V;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VRamDestroyInstance (void* Data)
|
||||
/* Destroy a chip instance */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
VRamInstance* V = Data;
|
||||
|
||||
/* Free X resources */
|
||||
XUndefineCursor (V->VicDisplay, V->VicWindow);
|
||||
XFreeGC (V->VicDisplay, V->VicGC);
|
||||
XDestroyWindow (V->VicDisplay, V->VicWindow);
|
||||
XCloseDisplay (V->VicDisplay);
|
||||
|
||||
/* Clear the global pointer */
|
||||
VRam = 0;
|
||||
|
||||
/* Free the instance data */
|
||||
Sim->Free (V);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VRamWrite (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
VRamInstance* V = Data;
|
||||
|
||||
/* Check the offset */
|
||||
if (Offs >= sizeof (V->Mem)) {
|
||||
Sim->Break ("VRAM: Accessing invalid memory at $%06X", V->Addr + Offs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write the value */
|
||||
V->Mem[Offs] = Val;
|
||||
|
||||
/* If this changes the visible part of the screen, schedule a redraw */
|
||||
if (Offs < 40*25) {
|
||||
|
||||
/* Schedule a redraw */
|
||||
VRamDrawChar (Offs);
|
||||
|
||||
/* Call the event loop */
|
||||
VRamEventLoop ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char VRamRead (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
VRamInstance* V = Data;
|
||||
|
||||
/* Check the offset */
|
||||
if (Offs >= sizeof (V->Mem)) {
|
||||
Sim->Break ("VRAM: Accessing invalid memory at $%06X", V->Addr + Offs);
|
||||
return 0xFF;
|
||||
} else {
|
||||
return V->Mem[Offs];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VRamDrawBorder (void)
|
||||
/* Draw the complete border */
|
||||
{
|
||||
if (Vic) {
|
||||
/* Set the border color */
|
||||
XSetForeground (VRam->VicDisplay, VRam->VicGC, VRam->Colors[Vic->Regs[32]].pixel);
|
||||
|
||||
/* Fill all rectangles that make the border */
|
||||
XFillRectangles (VRam->VicDisplay, VRam->VicWindow, VRam->VicGC,
|
||||
VRam->Border, sizeof (VRam->Border) / sizeof (VRam->Border[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VRamDrawChar (unsigned Offs)
|
||||
/* Draw one character at the given position */
|
||||
{
|
||||
unsigned Row, Col;
|
||||
XPoint Points[64];
|
||||
unsigned PCount;
|
||||
unsigned Color;
|
||||
|
||||
/* Get the character from the video RAM */
|
||||
unsigned char C = VRam->Mem[Offs];
|
||||
|
||||
/* Calculate the offset for the character data in the character ROM */
|
||||
unsigned char* D = VRam->CharRom + (C * 8);
|
||||
|
||||
/* Calculate the coords for the output */
|
||||
unsigned X = VRam->XOffs + (Offs % 40) * 8;
|
||||
unsigned Y = VRam->YOffs + (Offs / 40) * 8;
|
||||
|
||||
/* Clear the character area with the background color */
|
||||
XSetForeground (VRam->VicDisplay, VRam->VicGC, VRam->Colors[Vic->Regs[33]].pixel);
|
||||
XFillRectangle (VRam->VicDisplay, VRam->VicWindow, VRam->VicGC, X, Y, 8, 8);
|
||||
|
||||
/* Set the character color */
|
||||
Color = CRam? CRam->Mem[Offs] & 0x0F : VIC_WHITE;
|
||||
XSetForeground (VRam->VicDisplay, VRam->VicGC, VRam->Colors[Color].pixel);
|
||||
|
||||
/* Draw the foreground pixels */
|
||||
PCount = 0;
|
||||
for (Row = 0; Row < 8; ++Row) {
|
||||
|
||||
/* Get next byte from char rom */
|
||||
unsigned Data = *D++;
|
||||
|
||||
/* Make pixels from this byte */
|
||||
for (Col = 0; Col < 8; ++Col) {
|
||||
if (Data & 0x80) {
|
||||
/* Foreground pixel */
|
||||
Points[PCount].x = X + Col;
|
||||
Points[PCount].y = Y + Row;
|
||||
++PCount;
|
||||
}
|
||||
Data <<= 1;
|
||||
}
|
||||
}
|
||||
if (PCount) {
|
||||
XDrawPoints (VRam->VicDisplay, VRam->VicWindow, VRam->VicGC,
|
||||
Points, PCount, CoordModeOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VRamDrawArea (unsigned X1, unsigned Y1, unsigned X2, unsigned Y2)
|
||||
/* Update an area of the interior screen */
|
||||
{
|
||||
unsigned X, Y;
|
||||
|
||||
/* Check if we have to draw anything */
|
||||
if (X2 < VRam->XOffs || Y2 < VRam->YOffs ||
|
||||
X1 >= VRam->XOffs + VRam->XSize ||
|
||||
Y1 >= VRam->YOffs + VRam->YSize) {
|
||||
/* Completely outside */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make the coordinates relative to the interior */
|
||||
X1 -= VRam->XOffs;
|
||||
Y1 -= VRam->YOffs;
|
||||
X2 -= VRam->XOffs;
|
||||
Y2 -= VRam->YOffs;
|
||||
|
||||
/* Loop updating characters */
|
||||
for (Y = Y1; Y <= Y2; Y += 8) {
|
||||
for (X = X1; X <= X2; X += 8) {
|
||||
VRamDrawChar ((Y / 8) * 40 + (X / 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VRamDrawAllChars (void)
|
||||
/* Redraw the complete interior screen */
|
||||
{
|
||||
unsigned I;
|
||||
for (I = 0; I < 25*40; ++I) {
|
||||
VRamDrawChar (I);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void VRamEventLoop (void)
|
||||
/* Get all waiting events and handle them */
|
||||
{
|
||||
unsigned X1, Y1, X2, Y2;
|
||||
|
||||
/* Read input events */
|
||||
while (XEventsQueued (VRam->VicDisplay, QueuedAfterFlush) != 0) {
|
||||
|
||||
/* Read an event */
|
||||
XEvent Event;
|
||||
XNextEvent (VRam->VicDisplay, &Event);
|
||||
|
||||
switch (Event.type) {
|
||||
|
||||
case Expose:
|
||||
/* Calculate the area to redraw, then update the screen */
|
||||
X1 = Event.xexpose.x;
|
||||
Y1 = Event.xexpose.y;
|
||||
X2 = Event.xexpose.x + Event.xexpose.width - 1;
|
||||
Y2 = Event.xexpose.y + Event.xexpose.height - 1;
|
||||
if (X1 < VRam->XOffs || X2 > VRam->XOffs + VRam->XSize ||
|
||||
Y1 < VRam->YOffs || Y2 > VRam->YOffs + VRam->YSize) {
|
||||
/* Update the border */
|
||||
VRamDrawBorder ();
|
||||
}
|
||||
VRamDrawArea (X1, Y1, X2, Y2);
|
||||
break;
|
||||
|
||||
case MappingNotify:
|
||||
XRefreshKeyboardMapping (&Event.xmapping);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush the outgoing event queue */
|
||||
XFlush (VRam->VicDisplay);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Color RAM */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int CRamInitChip (const struct SimData* Data)
|
||||
/* Initialize the chip, return an error code */
|
||||
{
|
||||
/* Remember the pointer */
|
||||
Sim = Data;
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void* CRamCreateInstance (unsigned Addr, unsigned Range,
|
||||
void* CfgInfo attribute ((unused)))
|
||||
/* Create a new chip instance */
|
||||
{
|
||||
/* Allocate the instance data */
|
||||
CRamInstance* C = CRam = Sim->Malloc (sizeof (CRamInstance));
|
||||
|
||||
/* Remember a few settings */
|
||||
C->Addr = Addr;
|
||||
C->Range = Range;
|
||||
|
||||
/* Clear the color RAM memory */
|
||||
memset (C->Mem, 0x00, sizeof (C->Mem));
|
||||
|
||||
/* Return the instance data */
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CRamDestroyInstance (void* Data)
|
||||
/* Destroy a chip instance */
|
||||
{
|
||||
/* Clear the global pointer */
|
||||
CRam = 0;
|
||||
|
||||
/* Free the instance data */
|
||||
Sim->Free (Data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CRamWrite (void* Data, unsigned Offs, unsigned char Val)
|
||||
/* Write user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
CRamInstance* C = Data;
|
||||
|
||||
/* Check the offset */
|
||||
if (Offs >= sizeof (C->Mem)) {
|
||||
Sim->Break ("CRAM: Accessing invalid memory at $%06X", C->Addr + Offs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write the value */
|
||||
C->Mem[Offs] = Val & 0x0F;
|
||||
|
||||
/* If this changes the visible part of the screen, schedule a redraw */
|
||||
if (Offs < 40*25) {
|
||||
|
||||
/* Schedule a redraw */
|
||||
VRamDrawChar (Offs);
|
||||
|
||||
/* Call the event loop */
|
||||
VRamEventLoop ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char CRamRead (void* Data, unsigned Offs)
|
||||
/* Read user data */
|
||||
{
|
||||
/* Cast the data pointer */
|
||||
CRamInstance* C = Data;
|
||||
|
||||
/* Check the offset */
|
||||
if (Offs >= sizeof (C->Mem)) {
|
||||
Sim->Break ("CRAM: Accessing invalid memory at $%06X", C->Addr + Offs);
|
||||
return 0xFF;
|
||||
} else {
|
||||
return C->Mem[Offs] | 0xF0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,393 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* config.c */
|
||||
/* */
|
||||
/* Configuration file parsing for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "bitops.h"
|
||||
#include "print.h"
|
||||
#include "strutil.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "addrspace.h"
|
||||
#include "cfgdata.h"
|
||||
#include "chip.h"
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "location.h"
|
||||
#include "scanner.h"
|
||||
#include "config.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
|
||||
/* Check if the item is already defined. Print an error if so. If not, set
|
||||
* the marker that we have a definition now.
|
||||
*/
|
||||
{
|
||||
if (*Flags & Mask) {
|
||||
CfgError ("%s is already defined", Name);
|
||||
}
|
||||
*Flags |= Mask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
|
||||
/* Check that a mandatory attribute was given */
|
||||
{
|
||||
if ((Attr & Mask) == 0) {
|
||||
CfgError ("%s attribute is missing", Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseCPU (void)
|
||||
/* Parse a CPU section */
|
||||
{
|
||||
static const IdentTok Attributes [] = {
|
||||
{ "TYPE", CFGTOK_TYPE },
|
||||
{ "ADDRSPACE", CFGTOK_ADDRSPACE },
|
||||
};
|
||||
|
||||
enum {
|
||||
atNone = 0x0000,
|
||||
atType = 0x0001,
|
||||
atAddrSpace = 0x0002
|
||||
};
|
||||
unsigned Attr = 0;
|
||||
unsigned long Size = 0;
|
||||
|
||||
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
cfgtok_t AttrTok;
|
||||
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
|
||||
AttrTok = CfgTok;
|
||||
|
||||
/* An optional assignment follows */
|
||||
CfgNextTok ();
|
||||
CfgOptionalAssign ();
|
||||
|
||||
/* Check which attribute was given */
|
||||
switch (AttrTok) {
|
||||
|
||||
case CFGTOK_TYPE:
|
||||
FlagAttr (&Attr, atType, "TYPE");
|
||||
CfgAssureIdent ();
|
||||
/* ### */
|
||||
break;
|
||||
|
||||
case CFGTOK_ADDRSPACE:
|
||||
FlagAttr (&Attr, atAddrSpace, "ADDRSPACE");
|
||||
CfgAssureInt ();
|
||||
CfgRangeCheck (0x1000, 0x1000000);
|
||||
Size = CfgIVal;
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ("Unexpected attribute token");
|
||||
|
||||
}
|
||||
|
||||
/* Skip the attribute value and an optional comma */
|
||||
CfgNextTok ();
|
||||
CfgOptionalComma ();
|
||||
}
|
||||
|
||||
/* Must have some attributes */
|
||||
AttrCheck (Attr, atType, "TYPE");
|
||||
AttrCheck (Attr, atAddrSpace, "ADDRSPACE");
|
||||
|
||||
/* Create the system using the specified CPU */
|
||||
System = NewSystem (NewCPU ("6502", Size));
|
||||
|
||||
/* Skip the semicolon */
|
||||
CfgConsumeSemi ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseAddrSpace (void)
|
||||
/* Parse a ADDRSPACE section */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* CPU must be defined before the address space */
|
||||
if (System == 0) {
|
||||
CfgError ("CPU must be defined before address space definitions");
|
||||
}
|
||||
|
||||
/* Parse addresses */
|
||||
while (CfgTok == CFGTOK_INTCON) {
|
||||
|
||||
Location* L;
|
||||
|
||||
/* Remember the start address and skip it */
|
||||
unsigned long Start = CfgIVal;
|
||||
CfgNextTok ();
|
||||
|
||||
/* .. must follow */
|
||||
CfgConsume (CFGTOK_DOTDOT, "`..' expected");
|
||||
|
||||
/* End address must follow and must be greater than start */
|
||||
CfgAssureInt ();
|
||||
if (CfgIVal < Start) {
|
||||
CfgError ("Start address must be greater than end address");
|
||||
}
|
||||
|
||||
/* Create a new location and add it to the list */
|
||||
L = NewLocation (Start, CfgIVal);
|
||||
CollAppend (&Locations, L);
|
||||
|
||||
/* Skip the end address and the following colon */
|
||||
CfgNextTok ();
|
||||
CfgConsumeColon ();
|
||||
|
||||
/* Parse attributes terminated by a semicolon */
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Generate a new attribute with the given name, then skip it */
|
||||
CfgData* D = NewCfgData ();
|
||||
CfgNextTok ();
|
||||
|
||||
/* An optional assignment follows */
|
||||
CfgOptionalAssign ();
|
||||
|
||||
/* Check and assign the attribute value */
|
||||
switch (CfgTok) {
|
||||
|
||||
case CFGTOK_INTCON:
|
||||
D->Type = CfgDataNumber;
|
||||
D->V.IVal = CfgIVal;
|
||||
break;
|
||||
|
||||
case CFGTOK_STRCON:
|
||||
D->Type = CfgDataString;
|
||||
D->V.SVal = xstrdup (CfgSVal);
|
||||
break;
|
||||
|
||||
case CFGTOK_IDENT:
|
||||
D->Type = CfgDataId;
|
||||
D->V.SVal = xstrdup (CfgSVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
CfgError ("Invalid attribute type");
|
||||
}
|
||||
|
||||
/* Add the attribute to the location */
|
||||
CollAppend (&L->Attributes, D);
|
||||
|
||||
/* Skip the attribute value and an optional comma */
|
||||
CfgNextTok ();
|
||||
CfgOptionalComma ();
|
||||
}
|
||||
|
||||
/* Skip the semicolon */
|
||||
CfgConsumeSemi ();
|
||||
}
|
||||
|
||||
/* Sort all memory locations */
|
||||
LocationSort (&Locations);
|
||||
|
||||
/* Check the locations for overlaps and other problems */
|
||||
LocationCheck (&Locations);
|
||||
|
||||
/* Now create the chip instances. Since we can only mirror existing chips,
|
||||
* we will first create all real chips and the mirrors in a second run.
|
||||
*/
|
||||
for (I = 0; I < CollCount (&Locations); ++I) {
|
||||
|
||||
int Index;
|
||||
CfgData* D;
|
||||
unsigned Range; /* Address range for this chip */
|
||||
ChipInstance* CI;
|
||||
|
||||
/* Get this location */
|
||||
Location* L = CollAtUnchecked (&Locations, I);
|
||||
|
||||
/* Skip mirrors */
|
||||
if (LocationIsMirror (L)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The chip must have an attribute "name" of type string */
|
||||
Index = LocationGetAttr (L, "name");
|
||||
D = CollAt (&L->Attributes, Index);
|
||||
CfgDataCheckType (D, CfgDataString);
|
||||
|
||||
/* Remove the "name" attribute from the attribute list */
|
||||
CollDelete (&L->Attributes, Index);
|
||||
|
||||
/* Create the chip instance for the address range */
|
||||
Range = L->End - L->Start + 1;
|
||||
CI = NewChipInstance (D->V.SVal, L->Start, Range, &L->Attributes);
|
||||
|
||||
/* Delete the "name" attribute */
|
||||
FreeCfgData (D);
|
||||
|
||||
/* Assign the chip instance to address space */
|
||||
ASAssignChip (CPUInstance->AS, CI, L->Start, Range);
|
||||
}
|
||||
|
||||
/* Create the mirrors */
|
||||
for (I = 0; I < CollCount (&Locations); ++I) {
|
||||
|
||||
const CfgData* D;
|
||||
unsigned MirrorAddr; /* Mirror address */
|
||||
unsigned Range; /* Address range for this chip */
|
||||
unsigned Offs; /* Offset of the mirror */
|
||||
const ChipInstance* CI; /* Original chip instance */
|
||||
ChipInstance* MCI; /* Mirrored chip instance */
|
||||
|
||||
/* Get this location */
|
||||
const Location* L = CollAtUnchecked (&Locations, I);
|
||||
|
||||
/* Skip non mirrors */
|
||||
if (!LocationIsMirror (L)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate the address range */
|
||||
Range = L->End - L->Start;
|
||||
|
||||
/* Get the mirror address */
|
||||
D = CollConstAt (&L->Attributes, 0);
|
||||
MirrorAddr = (unsigned) D->V.IVal;
|
||||
|
||||
/* For simplicity, get the chip instance we're mirroring from the
|
||||
* memory, instead of searching for the range in the list.
|
||||
*/
|
||||
CI = ASGetChip (MirrorAddr);
|
||||
if (CI == 0) {
|
||||
/* We are mirroring an unassigned address */
|
||||
Error ("%s(%u): Mirroring an unassigned address",
|
||||
CfgGetName (), L->Line);
|
||||
}
|
||||
|
||||
/* Make sure we're mirroring the correct chip */
|
||||
CHECK (MirrorAddr >= CI->Addr && MirrorAddr < CI->Addr + CI->Size);
|
||||
|
||||
/* Calculate the offset of the mirror */
|
||||
Offs = MirrorAddr - CI->Addr;
|
||||
|
||||
/* Check if the mirror range is ok */
|
||||
if (Offs + Range > CI->Size) {
|
||||
Error ("%s(%u): Mirror range is too large", CfgGetName (), L->Line);
|
||||
}
|
||||
|
||||
/* Clone the chip instance for the new location */
|
||||
MCI = MirrorChipInstance (CI, L->Start - Offs);
|
||||
|
||||
/* Assign the chip instance to address space */
|
||||
ASAssignChip (CPUInstance->AS, MCI, L->Start, Range);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseConfig (void)
|
||||
/* Parse the config file */
|
||||
{
|
||||
static const IdentTok BlockNames [] = {
|
||||
{ "ADDRSPACE", CFGTOK_ADDRSPACE },
|
||||
{ "CPU", CFGTOK_CPU },
|
||||
};
|
||||
cfgtok_t BlockTok;
|
||||
|
||||
do {
|
||||
|
||||
/* Read the block ident */
|
||||
CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier");
|
||||
BlockTok = CfgTok;
|
||||
CfgNextTok ();
|
||||
|
||||
/* Expected a curly brace */
|
||||
CfgConsume (CFGTOK_LCURLY, "`{' expected");
|
||||
|
||||
/* Read the block */
|
||||
switch (BlockTok) {
|
||||
|
||||
case CFGTOK_ADDRSPACE:
|
||||
ParseAddrSpace ();
|
||||
break;
|
||||
|
||||
case CFGTOK_CPU:
|
||||
ParseCPU ();
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ("Unexpected block token");
|
||||
|
||||
}
|
||||
|
||||
/* Skip closing brace */
|
||||
CfgConsumeRCurly ();
|
||||
|
||||
} while (CfgTok != CFGTOK_EOF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgRead (void)
|
||||
/* Read the configuration */
|
||||
{
|
||||
/* If we have a config name given, open the file, otherwise we will read
|
||||
* from a buffer.
|
||||
*/
|
||||
CfgOpenInput ();
|
||||
|
||||
/* Parse the file */
|
||||
ParseConfig ();
|
||||
|
||||
/* Close the input file */
|
||||
CfgCloseInput ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,75 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* cpucore.c */
|
||||
/* */
|
||||
/* CPU definition for the simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "cpucore.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
CPUCore* NewCPUCore (const char* Name, unsigned AddrSpaceSize)
|
||||
/* Create and return a new CPU including it's address space */
|
||||
{
|
||||
CPUCore* C;
|
||||
|
||||
/* Make sure this is a 6502 CPU for now */
|
||||
if (strcmp (Name, "6502") != 0) {
|
||||
Error ("Unknown CPU type `%s'", Name);
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
C = xmalloc (sizeof (*C));
|
||||
|
||||
/* Initialize the data */
|
||||
C->Handle = 0; /* ### */
|
||||
C->AddressSize = AddrSpaceSize;
|
||||
|
||||
/* Return the new CPU core */
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* cpucore.h */
|
||||
/* */
|
||||
/* CPU definition for the simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CPUCORE_H
|
||||
#define CPUCORE_H
|
||||
|
||||
|
||||
|
||||
/* sim65 */
|
||||
#include "addrspace.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* CPU core structure */
|
||||
typedef struct CPUCore CPUCore;
|
||||
struct CPUCore {
|
||||
void* Handle; /* Pointer to shared lib handle */
|
||||
unsigned AddressSize; /* Size of the address space */
|
||||
|
||||
/* Callback functions */
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
CPUCore* NewCPUCore (const char* Name, unsigned AddrSpaceSize);
|
||||
/* Create and return a new CPU including it's address space */
|
||||
|
||||
|
||||
|
||||
/* End of cpucore.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -1,97 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* cpudata.h */
|
||||
/* */
|
||||
/* CPU data passed from the CPU plugins */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CPUDATA_H
|
||||
#define CPUDATA_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Version defines */
|
||||
#define CPUDATA_VER_MAJOR 1U
|
||||
#define CPUDATA_VER_MINOR 0U
|
||||
|
||||
/* Forwards */
|
||||
struct SimData;
|
||||
|
||||
/* CPUData structure */
|
||||
typedef struct CPUData CPUData;
|
||||
struct CPUData {
|
||||
const char* CPUName; /* Name of the chip */
|
||||
unsigned MajorVersion; /* Version information */
|
||||
unsigned MinorVersion;
|
||||
|
||||
/* -- Exported functions -- */
|
||||
|
||||
void (*Init) (const struct SimData* Data);
|
||||
/* Initialize the CPU module */
|
||||
|
||||
void* (*CreateInstance) (void* CfgInfo);
|
||||
/* Create an instance of the CPU. Return the instance data pointer */
|
||||
|
||||
void (*DestroyInstance) (void* Data);
|
||||
/* Destroy an instance of the CPU */
|
||||
|
||||
void (*Reset) (void* Data);
|
||||
/* Generate a CPU RESET */
|
||||
|
||||
void (*IRQRequest) (void* Data);
|
||||
/* Generate an IRQ */
|
||||
|
||||
void (*NMIRequest) (void* Data);
|
||||
/* Generate an NMI */
|
||||
|
||||
unsigned (*ExecuteInsn) (void* Data);
|
||||
/* Execute one CPU instruction. Return the number of clock cycles for the
|
||||
* executed instruction.
|
||||
*/
|
||||
|
||||
unsigned long (*GetCycles) (void* Data);
|
||||
/* Return the total number of clock cycles executed */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* End of cpudata.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,50 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* cputype.h */
|
||||
/* */
|
||||
/* CPU type definitions */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "cputype.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Current CPU */
|
||||
CPUType CPU = CPU_6502;
|
||||
|
||||
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* cputype.h */
|
||||
/* */
|
||||
/* CPU type definitions */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CPUTYPE_H
|
||||
#define CPUTYPE_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Supported CPUs */
|
||||
typedef enum CPUType {
|
||||
CPU_6502,
|
||||
CPU_65C02
|
||||
} CPUType;
|
||||
|
||||
/* Current CPU */
|
||||
extern CPUType CPU;
|
||||
|
||||
|
||||
|
||||
/* End of cputype.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -1,49 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* global.c */
|
||||
/* */
|
||||
/* Global variables for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
unsigned char Debug = 0; /* Debug mode */
|
||||
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* global.h */
|
||||
/* */
|
||||
/* Global variables for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
extern unsigned char Debug; /* Debug mode */
|
||||
|
||||
|
||||
|
||||
/* End of global.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -1,174 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* location.c */
|
||||
/* */
|
||||
/* Memory location description */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* common.h */
|
||||
#include "coll.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "cfgdata.h"
|
||||
#include "error.h"
|
||||
#include "scanner.h"
|
||||
#include "location.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* List of all memory locations */
|
||||
Collection Locations = STATIC_COLLECTION_INITIALIZER;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
Location* NewLocation (unsigned long Start, unsigned long End)
|
||||
/* Create a new location, initialize and return it */
|
||||
{
|
||||
/* Allocate memory */
|
||||
Location* L = xmalloc (sizeof (Location));
|
||||
|
||||
/* Initialize the fields */
|
||||
L->Start = Start;
|
||||
L->End = End;
|
||||
L->Attributes = EmptyCollection;
|
||||
L->Line = CfgErrorLine;
|
||||
L->Col = CfgErrorCol;
|
||||
|
||||
/* Return the new struct */
|
||||
return L;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int CmpLocations (void* Data attribute ((unused)),
|
||||
const void* lhs, const void* rhs)
|
||||
/* Compare function for CollSort */
|
||||
{
|
||||
/* Cast the object pointers */
|
||||
const Location* Left = (const Location*) rhs;
|
||||
const Location* Right = (const Location*) lhs;
|
||||
|
||||
/* Do the compare */
|
||||
if (Left->Start < Right->Start) {
|
||||
return 1;
|
||||
} else if (Left->Start > Right->Start) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int LocationGetAttr (const Location* L, const char* AttrName)
|
||||
/* Find the attribute with the given name and return it. Call Error() if the
|
||||
* attribute was not found.
|
||||
*/
|
||||
{
|
||||
int I = CfgDataFind (&L->Attributes, AttrName);
|
||||
if (I < 0) {
|
||||
Error ("%s(%u): Attribute `%s' missing", CfgGetName(), L->Line, AttrName);
|
||||
}
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int LocationIsMirror (const Location* L)
|
||||
/* Return true if the given location is a mirror of another one. */
|
||||
{
|
||||
/* Find the "mirror" attribute */
|
||||
return (CfgDataFind (&L->Attributes, "mirror") >= 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LocationSort (Collection* Locations)
|
||||
/* Sort all locations by address */
|
||||
{
|
||||
/* Sort all memory locations */
|
||||
CollSort (Locations, CmpLocations, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LocationCheck (const Collection* Locations)
|
||||
/* Check all locations for problems */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Check for overlaps and other problems */
|
||||
const Location* Last = 0;
|
||||
for (I = 0; I < CollCount (Locations); ++I) {
|
||||
|
||||
/* Get this location */
|
||||
const Location* L = CollConstAt (Locations, I);
|
||||
|
||||
/* Check for an overlap with the following location */
|
||||
if (Last && Last->End >= L->Start) {
|
||||
Error ("%s(%u): Address range overlap (overlapping entry is in line %u)",
|
||||
CfgGetName(), L->Line, Last->Line);
|
||||
}
|
||||
|
||||
/* If the location is a mirror, it must not have other attributes,
|
||||
* and the mirror attribute must be an integer.
|
||||
*/
|
||||
if (LocationIsMirror (L)) {
|
||||
const CfgData* D;
|
||||
if (CollCount (&L->Attributes) > 1) {
|
||||
Error ("%s(%u): Location at address $%06X is a mirror "
|
||||
"but has attributes", CfgGetName(), L->Line, L->Start);
|
||||
}
|
||||
D = CollConstAt (&L->Attributes, 0);
|
||||
CfgDataCheckType (D, CfgDataNumber);
|
||||
}
|
||||
|
||||
/* Remember this entry */
|
||||
Last = L;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,97 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* location.h */
|
||||
/* */
|
||||
/* Memory location description */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef LOCATION_H
|
||||
#define LOCATION_H
|
||||
|
||||
|
||||
|
||||
/* common.h */
|
||||
#include "coll.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* List of all memory locations */
|
||||
extern Collection Locations;
|
||||
|
||||
/* One memory location */
|
||||
typedef struct Location Location;
|
||||
struct Location {
|
||||
unsigned Start; /* Start of memory location */
|
||||
unsigned End; /* End memory location */
|
||||
Collection Attributes; /* Attributes given */
|
||||
unsigned Line; /* Line in config file */
|
||||
unsigned Col; /* Column in config file */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
Location* NewLocation (unsigned long Start, unsigned long End);
|
||||
/* Create a new location, initialize and return it */
|
||||
|
||||
int LocationGetAttr (const Location* L, const char* AttrName);
|
||||
/* Find the attribute with the given name and return it. Call Error() if the
|
||||
* attribute was not found.
|
||||
*/
|
||||
|
||||
int LocationIsMirror (const Location* L);
|
||||
/* Return true if the given location is a mirror of another one. */
|
||||
|
||||
void LocationSort (Collection* Locations);
|
||||
/* Sort all locations by address */
|
||||
|
||||
void LocationCheck (const Collection* Locations);
|
||||
/* Check all locations for problems */
|
||||
|
||||
|
||||
|
||||
/* End of location.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
217
src/sim65/main.c
217
src/sim65/main.c
@ -33,31 +33,31 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* common */
|
||||
#include "abend.h"
|
||||
#include "cmdline.h"
|
||||
#include "filestat.h"
|
||||
#include "print.h"
|
||||
#include "version.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chip.h"
|
||||
#include "chippath.h"
|
||||
#include "config.h"
|
||||
#include "cpucore.h"
|
||||
#include "cputype.h"
|
||||
#include "6502.h"
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "memory.h"
|
||||
#include "scanner.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Name of program file */
|
||||
const char* ProgramFile;
|
||||
|
||||
|
||||
|
||||
@ -71,18 +71,11 @@ static void Usage (void)
|
||||
{
|
||||
printf ("Usage: %s [options] file\n"
|
||||
"Short options:\n"
|
||||
" -C name\t\tUse simulator config file\n"
|
||||
" -L dir\t\tSet a chip directory search path\n"
|
||||
" -V\t\t\tPrint the simulator version number\n"
|
||||
" -d\t\t\tDebug mode\n"
|
||||
" -h\t\t\tHelp (this text)\n"
|
||||
" -v\t\t\tIncrease verbosity\n"
|
||||
" -V\t\t\tPrint the simulator version number\n"
|
||||
"\n"
|
||||
"Long options:\n"
|
||||
" --chipdir dir\t\tSet a chip directory search path\n"
|
||||
" --config name\t\tUse simulator config file\n"
|
||||
" --cpu type\t\tSet cpu type\n"
|
||||
" --debug\t\tDebug mode\n"
|
||||
" --help\t\tHelp (this text)\n"
|
||||
" --verbose\t\tIncrease verbosity\n"
|
||||
" --version\t\tPrint the simulator version number\n",
|
||||
@ -91,98 +84,6 @@ static void Usage (void)
|
||||
|
||||
|
||||
|
||||
static void OptChipDir (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Handle the --chipdir option */
|
||||
{
|
||||
struct dirent* E;
|
||||
|
||||
/* Get the length of the directory name */
|
||||
unsigned DirLen = strlen (Arg);
|
||||
|
||||
/* Open the directory */
|
||||
DIR* D = opendir (Arg);
|
||||
if (D == 0) {
|
||||
AbEnd ("Cannot read directory `%s': %s", Arg, strerror (errno));
|
||||
}
|
||||
|
||||
/* Read in all files and treat them as libraries */
|
||||
while ((E = readdir (D)) != 0) {
|
||||
|
||||
char* Name;
|
||||
struct stat S;
|
||||
|
||||
/* ### Ignore anything but *.so files */
|
||||
unsigned NameLen = strlen (E->d_name);
|
||||
if (NameLen <= 3) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp (E->d_name + NameLen - 3, ".so") != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create the full file name */
|
||||
Name = xmalloc (DirLen + 1 + NameLen + 1);
|
||||
strcpy (Name, Arg);
|
||||
strcpy (Name + DirLen, "/");
|
||||
strcpy (Name + DirLen + 1, E->d_name);
|
||||
|
||||
/* Stat the file */
|
||||
if (FileStat (Name, &S) != 0) {
|
||||
Warning ("Cannot stat `%s': %s", Name, strerror (errno));
|
||||
xfree (Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if this is a regular file */
|
||||
if (S_ISREG (S.st_mode)) {
|
||||
/* Treat it as a library */
|
||||
LoadChipLibrary (Name);
|
||||
}
|
||||
|
||||
/* Free the name */
|
||||
xfree (Name);
|
||||
}
|
||||
|
||||
/* Close the directory */
|
||||
closedir (D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptCPU (const char* Opt, const char* Arg)
|
||||
/* Handle the --cpu option */
|
||||
{
|
||||
if (strcmp (Arg, "6502") == 0) {
|
||||
CPU = CPU_6502;
|
||||
} else if (strcmp (Arg, "65C02") == 0) {
|
||||
CPU = CPU_65C02;
|
||||
} else {
|
||||
AbEnd ("Invalid argument for %s: `%s'", Opt, Arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Define the config file */
|
||||
{
|
||||
if (CfgAvail ()) {
|
||||
Error ("Cannot use -C twice");
|
||||
}
|
||||
CfgSetName (Arg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptDebug (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Simulator debug mode */
|
||||
{
|
||||
Debug = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptHelp (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Print usage information and exit */
|
||||
@ -204,21 +105,58 @@ static void OptVerbose (const char* Opt attribute ((unused)),
|
||||
|
||||
static void OptVersion (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Print the assembler version */
|
||||
/* Print the simulator version */
|
||||
{
|
||||
fprintf (stderr, "sim65 V%s\n", GetVersionAsString ());
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ReadProgramFile (void)
|
||||
/* Load program into memory */
|
||||
{
|
||||
int Val;
|
||||
unsigned Addr = 0x0200;
|
||||
|
||||
/* Open the file */
|
||||
FILE* F = fopen (ProgramFile, "rb");
|
||||
if (F == 0) {
|
||||
Error ("Cannot open `%s': %s", ProgramFile, strerror (errno));
|
||||
}
|
||||
|
||||
/* Get the CPU type from the file header */
|
||||
if ((Val = fgetc(F)) != EOF) {
|
||||
if (Val != CPU_6502 && Val != CPU_65C02) {
|
||||
Error ("`%s': Invalid CPU type", ProgramFile);
|
||||
}
|
||||
CPU = Val;
|
||||
}
|
||||
|
||||
/* Read the file body into memory */
|
||||
while ((Val = fgetc(F)) != EOF) {
|
||||
if (Addr == 0xFF00) {
|
||||
Error ("`%s': To large to fit into $0200-$FFF0", ProgramFile);
|
||||
}
|
||||
MemWriteByte (Addr++, (unsigned char) Val);
|
||||
}
|
||||
|
||||
/* Check for errors */
|
||||
if (ferror (F)) {
|
||||
Error ("Error reading from `%s': %s", ProgramFile, strerror (errno));
|
||||
}
|
||||
|
||||
/* Close the file */
|
||||
fclose (F);
|
||||
|
||||
Print (stdout, 1, "Loaded `%s' at $0200-$%04X\n", ProgramFile, Addr - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
/* Program long options */
|
||||
static const LongOpt OptTab[] = {
|
||||
{ "--chipdir", 1, OptChipDir },
|
||||
{ "--config", 1, OptConfig },
|
||||
{ "--cpu", 1, OptCPU },
|
||||
{ "--debug", 0, OptDebug },
|
||||
{ "--help", 0, OptHelp },
|
||||
{ "--verbose", 0, OptVerbose },
|
||||
{ "--version", 0, OptVersion },
|
||||
@ -226,15 +164,9 @@ int main (int argc, char* argv[])
|
||||
|
||||
unsigned I;
|
||||
|
||||
/* Initialize the output file name */
|
||||
const char* InputFile = 0;
|
||||
|
||||
/* Initialize the cmdline module */
|
||||
InitCmdLine (&argc, &argv, "sim65");
|
||||
|
||||
/* Initialize the chip library search paths */
|
||||
InitChipPaths ();
|
||||
|
||||
/* Parse the command line */
|
||||
I = 1;
|
||||
while (I < ArgCount) {
|
||||
@ -251,10 +183,6 @@ int main (int argc, char* argv[])
|
||||
LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
OptDebug (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
OptHelp (Arg, 0);
|
||||
@ -264,14 +192,6 @@ int main (int argc, char* argv[])
|
||||
OptVerbose (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
OptConfig (Arg, GetArg (&I, 2));
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
OptChipDir (Arg, GetArg (&I, 2));
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
OptVersion (Arg, 0);
|
||||
break;
|
||||
@ -281,10 +201,11 @@ int main (int argc, char* argv[])
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (InputFile) {
|
||||
fprintf (stderr, "additional file specs ignored\n");
|
||||
/* Filename. Check if we already had one */
|
||||
if (ProgramFile) {
|
||||
AbEnd ("Don't know what to do with `%s'", Arg);
|
||||
} else {
|
||||
InputFile = Arg;
|
||||
ProgramFile = Arg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,29 +213,21 @@ int main (int argc, char* argv[])
|
||||
++I;
|
||||
}
|
||||
|
||||
/* Sort the already loaded chips */
|
||||
SortChips ();
|
||||
|
||||
/* Check if we have a valid configuration */
|
||||
if (!CfgAvail ()) {
|
||||
Error ("Simulator configuration missing");
|
||||
/* Do we have a program file? */
|
||||
if (ProgramFile == 0) {
|
||||
AbEnd ("No program file");
|
||||
}
|
||||
|
||||
/* Initialize the simulated CPU memory */
|
||||
MemInit ();
|
||||
|
||||
/* Read the config file */
|
||||
CfgRead ();
|
||||
ReadProgramFile ();
|
||||
|
||||
CPUInit ();
|
||||
Reset ();
|
||||
|
||||
while (1) {
|
||||
CPURun ();
|
||||
ExecuteInsn ();
|
||||
}
|
||||
|
||||
/* Return an apropriate exit code */
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -33,18 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chip.h"
|
||||
#include "cputype.h"
|
||||
#include "error.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
@ -55,9 +45,8 @@
|
||||
|
||||
|
||||
|
||||
/* Pointer to our memory */
|
||||
static const ChipInstance** MemData = 0;
|
||||
unsigned MemSize = 0;
|
||||
/* THE memory */
|
||||
static unsigned char Mem[0x10000];
|
||||
|
||||
|
||||
|
||||
@ -70,15 +59,7 @@ unsigned MemSize = 0;
|
||||
void MemWriteByte (unsigned Addr, unsigned char Val)
|
||||
/* Write a byte to a memory location */
|
||||
{
|
||||
/* Get the instance of the chip at this address */
|
||||
const ChipInstance* CI = MemData[Addr];
|
||||
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Warning ("Writing to unassigned memory at $%06X", Addr);
|
||||
} else {
|
||||
CI->C->Data->Write (CI->Data, Addr - CI->Addr, Val);
|
||||
}
|
||||
Mem[Addr] = Val;
|
||||
}
|
||||
|
||||
|
||||
@ -86,16 +67,7 @@ void MemWriteByte (unsigned Addr, unsigned char Val)
|
||||
unsigned char MemReadByte (unsigned Addr)
|
||||
/* Read a byte from a memory location */
|
||||
{
|
||||
/* Get the instance of the chip at this address */
|
||||
const ChipInstance* CI = MemData[Addr];
|
||||
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Warning ("Reading from unassigned memory at $%06X", Addr);
|
||||
return 0xFF;
|
||||
} else {
|
||||
return CI->C->Data->Read (CI->Data, Addr - CI->Addr);
|
||||
}
|
||||
return Mem[Addr];
|
||||
}
|
||||
|
||||
|
||||
@ -121,54 +93,13 @@ unsigned MemReadZPWord (unsigned char Addr)
|
||||
|
||||
|
||||
|
||||
void MemAssignChip (const ChipInstance* CI, unsigned Addr, unsigned Range)
|
||||
/* Assign a chip instance to memory locations */
|
||||
{
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr + Range <= MemSize);
|
||||
|
||||
/* Assign the chip instance */
|
||||
while (Range--) {
|
||||
CHECK (MemData[Addr] == 0);
|
||||
MemData[Addr++] = CI;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const struct ChipInstance* MemGetChip (unsigned Addr)
|
||||
/* Get the chip that is located at the given address (may return NULL). */
|
||||
{
|
||||
/* Make sure, the address is valid */
|
||||
PRECONDITION (Addr < MemSize);
|
||||
|
||||
/* Return the chip instance */
|
||||
return MemData[Addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MemInit (void)
|
||||
/* Initialize the memory subsystem */
|
||||
{
|
||||
unsigned I;
|
||||
/* Fill momory with illegal opcode */
|
||||
memset (Mem, 0xFF, sizeof (Mem));
|
||||
|
||||
/* Allocate memory depending on the CPU type */
|
||||
switch (CPU) {
|
||||
case CPU_6502:
|
||||
case CPU_65C02:
|
||||
MemSize = 0x10000;
|
||||
break;
|
||||
default:
|
||||
Internal ("Unexpected CPU type: %d", CPU);
|
||||
}
|
||||
MemData = xmalloc (MemSize * sizeof (ChipInstance*));
|
||||
|
||||
/* Clear the memory */
|
||||
for (I = 0; I < MemSize; ++I) {
|
||||
MemData[I] = 0;
|
||||
}
|
||||
/* Set RESET vector to 0x0200 */
|
||||
Mem[0xFFFC] = 0x00;
|
||||
Mem[0xFFFD] = 0x02;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -38,20 +38,6 @@
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Forwards */
|
||||
struct ChipInstance;
|
||||
|
||||
/* Memory size of the CPU */
|
||||
extern unsigned MemSize;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -73,12 +59,6 @@ unsigned MemReadZPWord (unsigned char Addr);
|
||||
* overflow.
|
||||
*/
|
||||
|
||||
void MemAssignChip (const struct ChipInstance* CI, unsigned Addr, unsigned Range);
|
||||
/* Assign a chip instance to memory locations */
|
||||
|
||||
const struct ChipInstance* MemGetChip (unsigned Addr);
|
||||
/* Get the chip that is located at the given address (may return NULL). */
|
||||
|
||||
void MemInit (void);
|
||||
/* Initialize the memory subsystem */
|
||||
|
||||
|
255
src/sim65/paravirt.c
Normal file
255
src/sim65/paravirt.c
Normal file
@ -0,0 +1,255 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* paravirt.c */
|
||||
/* */
|
||||
/* Paravirtualization for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2013-2013 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#if defined(_MSC_VER)
|
||||
/* Microsoft compiler */
|
||||
# include <io.h>
|
||||
# pragma warning(disable : 4996)
|
||||
# define O_INITIAL O_BINARY
|
||||
#else
|
||||
/* Anyone else */
|
||||
# include <unistd.h>
|
||||
# define O_INITIAL 0
|
||||
#endif
|
||||
|
||||
/* common */
|
||||
#include "print.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "6502.h"
|
||||
#include "memory.h"
|
||||
#include "paravirt.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
typedef void (*PVFunc) (CPURegs* Regs);
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static unsigned char Pop (CPURegs* Regs)
|
||||
{
|
||||
return MemReadByte (0x0100 + ++Regs->SP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned PopParam (unsigned char Incr)
|
||||
{
|
||||
unsigned SP = MemReadZPWord (0x00);
|
||||
unsigned Val = MemReadWord (SP);
|
||||
SP += Incr;
|
||||
MemWriteByte (0x00, SP);
|
||||
SP >>= 8;
|
||||
MemWriteByte (0x01, SP);
|
||||
return Val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void PVExit (CPURegs* Regs)
|
||||
{
|
||||
Print (stdout, 1, "PVExit ($%02X)\n", Regs->AC);
|
||||
|
||||
exit (Regs->AC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void PVOpen (CPURegs* Regs)
|
||||
{
|
||||
char Path[1024];
|
||||
int OFlag = O_INITIAL;
|
||||
unsigned RetVal, I = 0;
|
||||
|
||||
unsigned Mode = PopParam (Regs->YR - 4);
|
||||
unsigned Flags = PopParam (2);
|
||||
unsigned Name = PopParam (2);
|
||||
|
||||
do {
|
||||
Path[I] = MemReadByte (Name++);
|
||||
}
|
||||
while (Path[I++]);
|
||||
|
||||
Print (stdout, 2, "PVOpen (\"%s\", $%04X)\n", Path, Flags);
|
||||
|
||||
switch (Flags & 0x03) {
|
||||
case 0x01:
|
||||
OFlag |= O_RDONLY;
|
||||
break;
|
||||
case 0x02:
|
||||
OFlag |= O_WRONLY;
|
||||
break;
|
||||
case 0x03:
|
||||
OFlag |= O_RDWR;
|
||||
break;
|
||||
}
|
||||
if (Flags & 0x10) {
|
||||
OFlag |= O_CREAT;
|
||||
}
|
||||
if (Flags & 0x20) {
|
||||
OFlag |= O_TRUNC;
|
||||
}
|
||||
if (Flags & 0x40) {
|
||||
OFlag |= O_APPEND;
|
||||
}
|
||||
if (Flags & 0x80) {
|
||||
OFlag |= O_EXCL;
|
||||
}
|
||||
|
||||
/* Avoid gcc warning */
|
||||
(void) Mode;
|
||||
|
||||
RetVal = open (Path, OFlag);
|
||||
|
||||
Regs->AC = RetVal & 0xFF;
|
||||
RetVal >>= 8;
|
||||
Regs->XR = RetVal & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void PVClose (CPURegs* Regs)
|
||||
{
|
||||
unsigned RetVal;
|
||||
|
||||
unsigned FD = Regs->AC + (Regs->XR << 8);
|
||||
|
||||
Print (stdout, 2, "PVClose ($%04X)\n", FD);
|
||||
|
||||
RetVal = close (FD);
|
||||
|
||||
Regs->AC = RetVal & 0xFF;
|
||||
RetVal >>= 8;
|
||||
Regs->XR = RetVal & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void PVRead (CPURegs* Regs)
|
||||
{
|
||||
unsigned char* Data;
|
||||
unsigned RetVal, I = 0;
|
||||
|
||||
unsigned Count = Regs->AC + (Regs->XR << 8);
|
||||
unsigned Buf = PopParam (2);
|
||||
unsigned FD = PopParam (2);
|
||||
|
||||
Print (stdout, 2, "PVRead ($%04X, $%04X, $%04X)\n", FD, Buf, Count);
|
||||
|
||||
Data = xmalloc (Count);
|
||||
|
||||
RetVal = read (FD, Data, Count);
|
||||
|
||||
if (RetVal != (unsigned) -1) {
|
||||
while (I < RetVal) {
|
||||
MemWriteByte (Buf++, Data[I++]);
|
||||
}
|
||||
}
|
||||
xfree (Data);
|
||||
|
||||
Regs->AC = RetVal & 0xFF;
|
||||
RetVal >>= 8;
|
||||
Regs->XR = RetVal & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void PVWrite (CPURegs* Regs)
|
||||
{
|
||||
unsigned char* Data;
|
||||
unsigned RetVal, I = 0;
|
||||
|
||||
unsigned Count = Regs->AC + (Regs->XR << 8);
|
||||
unsigned Buf = PopParam (2);
|
||||
unsigned FD = PopParam (2);
|
||||
|
||||
Print (stdout, 2, "PVWrite ($%04X, $%04X, $%04X)\n", FD, Buf, Count);
|
||||
|
||||
Data = xmalloc (Count);
|
||||
while (I < Count) {
|
||||
Data[I++] = MemReadByte (Buf++);
|
||||
}
|
||||
|
||||
RetVal = write (FD, Data, Count);
|
||||
|
||||
xfree (Data);
|
||||
|
||||
Regs->AC = RetVal & 0xFF;
|
||||
RetVal >>= 8;
|
||||
Regs->XR = RetVal & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const PVFunc Hooks[] = {
|
||||
PVExit,
|
||||
PVOpen,
|
||||
PVClose,
|
||||
PVRead,
|
||||
PVWrite,
|
||||
};
|
||||
|
||||
|
||||
|
||||
void ParaVirtualization (CPURegs* Regs)
|
||||
/* Potentially execute paravirtualization hook */
|
||||
{
|
||||
/* Check for paravirtualization address range */
|
||||
if (Regs->PC < 0xFFF0 ||
|
||||
Regs->PC >= 0xFFF0 + sizeof (Hooks) / sizeof (Hooks[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call paravirtualization hook */
|
||||
Hooks[Regs->PC - 0xFFF0] (Regs);
|
||||
|
||||
/* Simulate RTS */
|
||||
Regs->PC = Pop(Regs) + (Pop(Regs) << 8) + 1;
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* config.h */
|
||||
/* paravirt.h */
|
||||
/* */
|
||||
/* Configuration file parsing for the sim65 6502 simulator */
|
||||
/* Paravirtualization for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* (C) 2013-2013 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -33,8 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
#ifndef PARAVIRT_H
|
||||
#define PARAVIRT_H
|
||||
|
||||
|
||||
|
||||
@ -44,16 +44,11 @@
|
||||
|
||||
|
||||
|
||||
void CfgRead (void);
|
||||
/* Read the configuration */
|
||||
void ParaVirtualization (CPURegs* Regs);
|
||||
/* Potentially execute paravirtualization hook */
|
||||
|
||||
|
||||
|
||||
/* End of config.h */
|
||||
/* End of paravirt.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,530 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* scanner.c */
|
||||
/* */
|
||||
/* Configuration file scanner for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* common */
|
||||
#include "chartype.h"
|
||||
#include "xsprintf.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "error.h"
|
||||
#include "scanner.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Current token and attributes */
|
||||
cfgtok_t CfgTok;
|
||||
StrBuf CfgSVal = STATIC_STRBUF_INITIALIZER;
|
||||
unsigned long CfgIVal;
|
||||
|
||||
/* Error location */
|
||||
unsigned CfgErrorLine;
|
||||
unsigned CfgErrorCol;
|
||||
|
||||
/* Input sources for the configuration */
|
||||
static const char* CfgName = 0;
|
||||
static const char* CfgBuf = 0;
|
||||
|
||||
/* Other input stuff */
|
||||
static int C = ' ';
|
||||
static unsigned InputLine = 1;
|
||||
static unsigned InputCol = 0;
|
||||
static FILE* InputFile = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Error handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void CfgWarning (const char* Format, ...)
|
||||
/* Print a warning message adding file name and line number of the config file */
|
||||
{
|
||||
char Buf [512];
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, Format);
|
||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||
va_end (ap);
|
||||
|
||||
Warning ("%s(%u): %s", CfgGetName(), CfgErrorLine, Buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgError (const char* Format, ...)
|
||||
/* Print an error message adding file name and line number of the config file */
|
||||
{
|
||||
char Buf [512];
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, Format);
|
||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||
va_end (ap);
|
||||
|
||||
Error ("%s(%u): %s", CfgGetName(), CfgErrorLine, Buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void NextChar (void)
|
||||
/* Read the next character from the input file */
|
||||
{
|
||||
if (CfgBuf) {
|
||||
/* Read from buffer */
|
||||
C = (unsigned char)(*CfgBuf);
|
||||
if (C == 0) {
|
||||
C = EOF;
|
||||
} else {
|
||||
++CfgBuf;
|
||||
}
|
||||
} else {
|
||||
/* Read from the file */
|
||||
C = getc (InputFile);
|
||||
}
|
||||
|
||||
/* Count columns */
|
||||
if (C != EOF) {
|
||||
++InputCol;
|
||||
}
|
||||
|
||||
/* Count lines */
|
||||
if (C == '\n') {
|
||||
++InputLine;
|
||||
InputCol = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned DigitVal (int C)
|
||||
/* Return the value for a numeric digit */
|
||||
{
|
||||
if (isdigit (C)) {
|
||||
return C - '0';
|
||||
} else {
|
||||
return toupper (C) - 'A' + 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgNextTok (void)
|
||||
/* Read the next token from the input stream */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
|
||||
Again:
|
||||
/* Skip whitespace */
|
||||
while (isspace (C)) {
|
||||
NextChar ();
|
||||
}
|
||||
|
||||
/* Remember the current position */
|
||||
CfgErrorLine = InputLine;
|
||||
CfgErrorCol = InputCol;
|
||||
|
||||
/* Identifier? */
|
||||
if (C == '_' || IsAlpha (C)) {
|
||||
|
||||
/* Read the identifier */
|
||||
I = 0;
|
||||
while (C == '_' || IsAlNum (C)) {
|
||||
if (I < CFG_MAX_IDENT_LEN) {
|
||||
CfgSVal [I++] = C;
|
||||
}
|
||||
NextChar ();
|
||||
}
|
||||
CfgSVal [I] = '\0';
|
||||
CfgTok = CFGTOK_IDENT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Hex number? */
|
||||
if (C == '$') {
|
||||
NextChar ();
|
||||
if (!isxdigit (C)) {
|
||||
Error ("%s(%u): Hex digit expected", CfgName, InputLine);
|
||||
}
|
||||
CfgIVal = 0;
|
||||
while (isxdigit (C)) {
|
||||
CfgIVal = CfgIVal * 16 + DigitVal (C);
|
||||
NextChar ();
|
||||
}
|
||||
CfgTok = CFGTOK_INTCON;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Decimal number? */
|
||||
if (isdigit (C)) {
|
||||
CfgIVal = 0;
|
||||
while (isdigit (C)) {
|
||||
CfgIVal = CfgIVal * 10 + DigitVal (C);
|
||||
NextChar ();
|
||||
}
|
||||
CfgTok = CFGTOK_INTCON;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Other characters */
|
||||
switch (C) {
|
||||
|
||||
case '{':
|
||||
NextChar ();
|
||||
CfgTok = CFGTOK_LCURLY;
|
||||
break;
|
||||
|
||||
case '}':
|
||||
NextChar ();
|
||||
CfgTok = CFGTOK_RCURLY;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
NextChar ();
|
||||
CfgTok = CFGTOK_SEMI;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
NextChar ();
|
||||
if (C == '.') {
|
||||
NextChar ();
|
||||
CfgTok = CFGTOK_DOTDOT;
|
||||
} else {
|
||||
CfgTok = CFGTOK_DOT;
|
||||
}
|
||||
break;
|
||||
|
||||
case ',':
|
||||
NextChar ();
|
||||
CfgTok = CFGTOK_COMMA;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
NextChar ();
|
||||
CfgTok = CFGTOK_EQ;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
NextChar ();
|
||||
CfgTok = CFGTOK_COLON;
|
||||
break;
|
||||
|
||||
case '\"':
|
||||
NextChar ();
|
||||
I = 0;
|
||||
while (C != '\"') {
|
||||
if (C == EOF || C == '\n') {
|
||||
Error ("%s(%u): Unterminated string", CfgName, InputLine);
|
||||
}
|
||||
if (I < CFG_MAX_IDENT_LEN) {
|
||||
CfgSVal [I++] = C;
|
||||
}
|
||||
NextChar ();
|
||||
}
|
||||
NextChar ();
|
||||
CfgSVal [I] = '\0';
|
||||
CfgTok = CFGTOK_STRCON;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
/* Comment */
|
||||
while (C != '\n' && C != EOF) {
|
||||
NextChar ();
|
||||
}
|
||||
if (C != EOF) {
|
||||
goto Again;
|
||||
}
|
||||
CfgTok = CFGTOK_EOF;
|
||||
break;
|
||||
|
||||
case EOF:
|
||||
CfgTok = CFGTOK_EOF;
|
||||
break;
|
||||
|
||||
default:
|
||||
Error ("%s(%u): Invalid character `%c'", CfgName, InputLine, C);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgConsume (cfgtok_t T, const char* Msg)
|
||||
/* Skip a token, print an error message if not found */
|
||||
{
|
||||
if (CfgTok != T) {
|
||||
CfgError ("%s", Msg);
|
||||
}
|
||||
CfgNextTok ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgConsumeSemi (void)
|
||||
/* Consume a semicolon */
|
||||
{
|
||||
CfgConsume (CFGTOK_SEMI, "`;' expected");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgConsumeColon (void)
|
||||
/* Consume a colon */
|
||||
{
|
||||
CfgConsume (CFGTOK_COLON, "`:' expected");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgConsumeRCurly (void)
|
||||
/* Consume a right curly brace */
|
||||
{
|
||||
CfgConsume (CFGTOK_RCURLY, "`}' expected");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgOptionalComma (void)
|
||||
/* Consume a comma if there is one */
|
||||
{
|
||||
if (CfgTok == CFGTOK_COMMA) {
|
||||
CfgNextTok ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgOptionalAssign (void)
|
||||
/* Consume an equal sign if there is one */
|
||||
{
|
||||
if (CfgTok == CFGTOK_EQ) {
|
||||
CfgNextTok ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgAssureInt (void)
|
||||
/* Make sure the next token is an integer */
|
||||
{
|
||||
if (CfgTok != CFGTOK_INTCON) {
|
||||
CfgError ("Integer constant expected");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgAssureStr (void)
|
||||
/* Make sure the next token is a string constant */
|
||||
{
|
||||
if (CfgTok != CFGTOK_STRCON) {
|
||||
CfgError ("String constant expected");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgAssureIdent (void)
|
||||
/* Make sure the next token is an identifier */
|
||||
{
|
||||
if (CfgTok != CFGTOK_IDENT) {
|
||||
CfgError ("Identifier expected");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgRangeCheck (unsigned long Lo, unsigned long Hi)
|
||||
/* Check the range of CfgIVal */
|
||||
{
|
||||
if (CfgIVal < Lo || CfgIVal > Hi) {
|
||||
CfgError ("Range error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
|
||||
/* Map an identifier to one of the special tokens in the table */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* We need an identifier */
|
||||
if (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Make it upper case */
|
||||
I = 0;
|
||||
while (CfgSVal [I]) {
|
||||
CfgSVal [I] = toupper (CfgSVal [I]);
|
||||
++I;
|
||||
}
|
||||
|
||||
/* Linear search */
|
||||
for (I = 0; I < Size; ++I) {
|
||||
if (strcmp (CfgSVal, Table [I].Ident) == 0) {
|
||||
CfgTok = Table [I].Tok;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Not found or no identifier */
|
||||
Error ("%s(%u): %s expected", CfgName, InputLine, Name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgBoolToken (void)
|
||||
/* Map an identifier or integer to a boolean token */
|
||||
{
|
||||
static const IdentTok Booleans [] = {
|
||||
{ "YES", CFGTOK_TRUE },
|
||||
{ "NO", CFGTOK_FALSE },
|
||||
{ "TRUE", CFGTOK_TRUE },
|
||||
{ "FALSE", CFGTOK_FALSE },
|
||||
};
|
||||
|
||||
/* If we have an identifier, map it to a boolean token */
|
||||
if (CfgTok == CFGTOK_IDENT) {
|
||||
CfgSpecialToken (Booleans, ENTRY_COUNT (Booleans), "Boolean");
|
||||
} else {
|
||||
/* We expected an integer here */
|
||||
if (CfgTok != CFGTOK_INTCON) {
|
||||
CfgError ("Boolean value expected");
|
||||
}
|
||||
CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgSetName (const char* Name)
|
||||
/* Set a name for a config file */
|
||||
{
|
||||
CfgName = Name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* CfgGetName (void)
|
||||
/* Get the name of the config file */
|
||||
{
|
||||
if (CfgName) {
|
||||
return CfgName;
|
||||
} else if (CfgBuf) {
|
||||
return "[builtin config]";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgSetBuf (const char* Buf)
|
||||
/* Set a memory buffer for the config */
|
||||
{
|
||||
CfgBuf = Buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CfgAvail (void)
|
||||
/* Return true if we have a configuration available */
|
||||
{
|
||||
return CfgName != 0 || CfgBuf != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgOpenInput (void)
|
||||
/* Open the input file if we have one */
|
||||
{
|
||||
/* If we have a config name given, open the file, otherwise we will read
|
||||
* from a buffer.
|
||||
*/
|
||||
if (!CfgBuf) {
|
||||
|
||||
/* Open the file */
|
||||
InputFile = fopen (CfgName, "r");
|
||||
if (InputFile == 0) {
|
||||
Error ("Cannot open `%s': %s", CfgName, strerror (errno));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Initialize variables */
|
||||
C = ' ';
|
||||
InputLine = 1;
|
||||
InputCol = 0;
|
||||
|
||||
/* Start the ball rolling ... */
|
||||
CfgNextTok ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgCloseInput (void)
|
||||
/* Close the input file if we have one */
|
||||
{
|
||||
/* Close the input file if we had one */
|
||||
if (InputFile) {
|
||||
(void) fclose (InputFile);
|
||||
InputFile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,180 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* scanner.h */
|
||||
/* */
|
||||
/* Configuration file scanner for the sim65 6502 simulator */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef SCANNER_H
|
||||
#define SCANNER_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Config file tokens */
|
||||
typedef enum {
|
||||
CFGTOK_NONE,
|
||||
CFGTOK_INTCON,
|
||||
CFGTOK_STRCON,
|
||||
CFGTOK_IDENT,
|
||||
CFGTOK_LCURLY,
|
||||
CFGTOK_RCURLY,
|
||||
CFGTOK_SEMI,
|
||||
CFGTOK_COMMA,
|
||||
CFGTOK_EQ,
|
||||
CFGTOK_COLON,
|
||||
CFGTOK_DOT,
|
||||
CFGTOK_DOTDOT,
|
||||
CFGTOK_EOF,
|
||||
|
||||
/* Primary blocks */
|
||||
CFGTOK_CPU,
|
||||
CFGTOK_ADDRSPACE,
|
||||
|
||||
/* Secondary stuff */
|
||||
CFGTOK_TYPE,
|
||||
|
||||
/* Special identifiers */
|
||||
CFGTOK_TRUE,
|
||||
CFGTOK_FALSE
|
||||
|
||||
} cfgtok_t;
|
||||
|
||||
|
||||
|
||||
/* Mapping table entry, special identifier --> token */
|
||||
typedef struct IdentTok IdentTok;
|
||||
struct IdentTok {
|
||||
const char* Ident; /* Identifier */
|
||||
cfgtok_t Tok; /* Token for identifier */
|
||||
};
|
||||
#define ENTRY_COUNT(s) (sizeof (s) / sizeof (s [0]))
|
||||
|
||||
|
||||
|
||||
/* Current token and attributes */
|
||||
extern cfgtok_t CfgTok;
|
||||
extern StrBuf CfgSVal;
|
||||
extern unsigned long CfgIVal;
|
||||
|
||||
/* Error location */
|
||||
extern unsigned CfgErrorLine;
|
||||
extern unsigned CfgErrorCol;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void CfgWarning (const char* Format, ...) attribute((format(printf,1,2)));
|
||||
/* Print a warning message adding file name and line number of the config file */
|
||||
|
||||
void CfgError (const char* Format, ...) attribute((format(printf,1,2)));
|
||||
/* Print an error message adding file name and line number of the config file */
|
||||
|
||||
void CfgNextTok (void);
|
||||
/* Read the next token from the input stream */
|
||||
|
||||
void CfgConsume (cfgtok_t T, const char* Msg);
|
||||
/* Skip a token, print an error message if not found */
|
||||
|
||||
void CfgConsumeSemi (void);
|
||||
/* Consume a semicolon */
|
||||
|
||||
void CfgConsumeColon (void);
|
||||
/* Consume a colon */
|
||||
|
||||
void CfgConsumeRCurly (void);
|
||||
/* Consume a right curly brace */
|
||||
|
||||
void CfgOptionalComma (void);
|
||||
/* Consume a comma if there is one */
|
||||
|
||||
void CfgOptionalAssign (void);
|
||||
/* Consume an equal sign if there is one */
|
||||
|
||||
void CfgAssureInt (void);
|
||||
/* Make sure the next token is an integer */
|
||||
|
||||
void CfgAssureStr (void);
|
||||
/* Make sure the next token is a string constant */
|
||||
|
||||
void CfgAssureIdent (void);
|
||||
/* Make sure the next token is an identifier */
|
||||
|
||||
void CfgRangeCheck (unsigned long Lo, unsigned long Hi);
|
||||
/* Check the range of CfgIVal */
|
||||
|
||||
void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name);
|
||||
/* Map an identifier to one of the special tokens in the table */
|
||||
|
||||
void CfgBoolToken (void);
|
||||
/* Map an identifier or integer to a boolean token */
|
||||
|
||||
void CfgSetName (const char* Name);
|
||||
/* Set a name for a config file */
|
||||
|
||||
const char* CfgGetName (void);
|
||||
/* Get the name of the config file */
|
||||
|
||||
void CfgSetBuf (const char* Buf);
|
||||
/* Set a memory buffer for the config */
|
||||
|
||||
int CfgAvail (void);
|
||||
/* Return true if we have a configuration available */
|
||||
|
||||
void CfgOpenInput (void);
|
||||
/* Open the input file if we have one */
|
||||
|
||||
void CfgCloseInput (void);
|
||||
/* Close the input file if we have one */
|
||||
|
||||
|
||||
|
||||
/* End of scanner.h */
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,118 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* simdata.h */
|
||||
/* */
|
||||
/* Simulator data passed to the chip plugins */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef SIMDATA_H
|
||||
#define SIMDATA_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* SimData structure */
|
||||
typedef struct SimData SimData;
|
||||
struct SimData {
|
||||
unsigned MajorVersion;
|
||||
unsigned MinorVersion;
|
||||
|
||||
/* -- Callback functions -- */
|
||||
|
||||
void* (*Malloc) (size_t Size);
|
||||
/* Allocate a memory block of the given size */
|
||||
|
||||
void (*Free) (void* Block);
|
||||
/* Free an allocated memory block */
|
||||
|
||||
void (*Warning) (const char* Format, ...);
|
||||
/* Print a warning */
|
||||
|
||||
void (*Error) (const char* Format, ...);
|
||||
/* Print an error and terminate the program */
|
||||
|
||||
void (*Internal) (const char* Format, ...);
|
||||
/* Print an internal program error and terminate */
|
||||
|
||||
int (*GetCfgId) (void* CfgInfo, const char* Name, char** Id);
|
||||
/* Search CfgInfo for an attribute with the given name and type "id". If
|
||||
* found, remove it from the configuration, pass a pointer to a dynamically
|
||||
* allocated string containing the value to Id, and return true. If not
|
||||
* found, return false. The memory passed in Id must be free by a call to
|
||||
* Free();
|
||||
*/
|
||||
|
||||
int (*GetCfgStr) (void* CfgInfo, const char* Name, char** S);
|
||||
/* Search CfgInfo for an attribute with the given name and type "string".
|
||||
* If found, remove it from the configuration, pass a pointer to a
|
||||
* dynamically allocated string containing the value to S, and return
|
||||
* true. If not found, return false. The memory passed in S must be free
|
||||
* by a call to Free();
|
||||
*/
|
||||
|
||||
int (*GetCfgNum) (void* CfgInfo, const char* Name, long* Val);
|
||||
/* Search CfgInfo for an attribute with the given name and type "number".
|
||||
* If found, remove it from the configuration, copy it into Val and return
|
||||
* true. If not found, return false.
|
||||
*/
|
||||
|
||||
unsigned char (*ReadCtrl) (unsigned Addr);
|
||||
/* Read from the given address without triggering any additional action */
|
||||
|
||||
void (*WriteCtrl) (unsigned Addr, unsigned char Val);
|
||||
/* Write to the given address without triggering additional action */
|
||||
|
||||
void (*Break) (const char* Format, ...);
|
||||
/* Stop the CPU and display the given message */
|
||||
|
||||
void (*IRQ) (void);
|
||||
/* Issue an irq request */
|
||||
|
||||
void (*NMI) (void);
|
||||
/* Issue an nmi request */
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* End of simdata.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,70 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* system.c */
|
||||
/* */
|
||||
/* Description of the simulated system */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* common.h */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "system.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
System* NewSystem (CPUCore* CPU)
|
||||
/* Create and initialize a new System struct. The function will read the size
|
||||
* of the address space from the CPU, and also create a new AddressSpace
|
||||
* object. No chips are assigned, however.
|
||||
*/
|
||||
{
|
||||
/* Allocate memory */
|
||||
System* Sys = xmalloc (sizeof (System));
|
||||
|
||||
/* Initialize the fields */
|
||||
Sys->CPU = CPU;
|
||||
Sys->AS = NewAddressSpace (CPU->AddressSize);
|
||||
Sys->ChipInstances = AUTO_COLLECTION_INITIALIZER;
|
||||
|
||||
/* Return the new system */
|
||||
return Sys;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* system.h */
|
||||
/* */
|
||||
/* Description of the simulated system */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003-2012, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef SYSTEM_H
|
||||
#define SYSTEM_H
|
||||
|
||||
|
||||
|
||||
/* common.h */
|
||||
#include "coll.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "addrspace.h"
|
||||
#include "cpucore.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Forwards */
|
||||
struct CPUCore;
|
||||
|
||||
/* */
|
||||
typedef struct System System;
|
||||
struct System {
|
||||
CPUCore* CPU; /* The CPU in the system */
|
||||
AddressSpace* AS; /* The CPU address space */
|
||||
Collection ChipInstances; /* Instances of all the chips */
|
||||
};
|
||||
|
||||
/* Global pointer to simulated system */
|
||||
extern System* System;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
System* NewSystem (CPUCore* CPU);
|
||||
/* Create and initialize a new System struct. The function will read the size
|
||||
* of the address space from the CPU, and also create a new AddressSpace
|
||||
* object. No chips are assigned, however.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of system.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user