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.
grc65 \
ld65 \
od65 \
+ sim65 \
sp65
CA65_INC := $(abspath ../asminc)
{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
{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
--- /dev/null
+<?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>
\ No newline at end of file
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 6502.c */
+/* */
+/* CPU core for the 6502 */
+/* */
+/* */
+/* */
+/* (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 "memory.h"
+#include "error.h"
+#include "6502.h"
+#include "paravirt.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Current CPU */
+CPUType CPU;
+
+/* Type of an opcode handler function */
+typedef void (*OPFunc) (void);
+
+/* The CPU registers */
+static CPURegs Regs;
+
+/* Cycles for the current insn */
+static unsigned Cycles;
+
+/* Total number of CPU cycles exec'd */
+static unsigned long TotalCycles;
+
+/* NMI request active */
+static unsigned HaveNMIRequest;
+
+/* IRQ request active */
+static unsigned HaveIRQRequest;
+
+
+
+/*****************************************************************************/
+/* Helper functions and macros */
+/*****************************************************************************/
+
+
+
+/* Return the flags as a boolean value (0/1) */
+#define GET_CF() ((Regs.SR & CF) != 0)
+#define GET_ZF() ((Regs.SR & ZF) != 0)
+#define GET_IF() ((Regs.SR & IF) != 0)
+#define GET_DF() ((Regs.SR & DF) != 0)
+#define GET_BF() ((Regs.SR & BF) != 0)
+#define GET_OF() ((Regs.SR & OF) != 0)
+#define GET_SF() ((Regs.SR & SF) != 0)
+
+/* Set the flags. The parameter is a boolean flag that says if the flag should be
+ * set or reset.
+ */
+#define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0)
+#define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0)
+#define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0)
+#define SET_DF(f) do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0)
+#define SET_BF(f) do { if (f) { Regs.SR |= BF; } else { Regs.SR &= ~BF; } } while (0)
+#define SET_OF(f) do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0)
+#define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0)
+
+/* Special test and set macros. The meaning of the parameter depends on the
+ * actual flag that should be set or reset.
+ */
+#define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
+#define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
+#define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
+
+/* Program counter halves */
+#define PCL (Regs.PC & 0xFF)
+#define PCH ((Regs.PC >> 8) & 0xFF)
+
+/* Stack operations */
+#define PUSH(Val) MemWriteByte (0x0100 + Regs.SP--, Val)
+#define POP() MemReadByte (0x0100 + ++Regs.SP)
+
+/* Test for page cross */
+#define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
+
+/* #imm */
+#define AC_OP_IMM(op) \
+ Cycles = 2; \
+ Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 2
+
+/* zp */
+#define AC_OP_ZP(op) \
+ Cycles = 3; \
+ Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 2
+
+/* zp,x */
+#define AC_OP_ZPX(op) \
+ unsigned char ZPAddr; \
+ Cycles = 4; \
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
+ Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 2
+
+/* zp,y */
+#define AC_OP_ZPY(op) \
+ unsigned char ZPAddr; \
+ Cycles = 4; \
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \
+ Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 2
+
+/* abs */
+#define AC_OP_ABS(op) \
+ unsigned Addr; \
+ Cycles = 4; \
+ Addr = MemReadWord (Regs.PC+1); \
+ Regs.AC = Regs.AC op MemReadByte (Addr); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 3
+
+/* abs,x */
+#define AC_OP_ABSX(op) \
+ unsigned Addr; \
+ Cycles = 4; \
+ Addr = MemReadWord (Regs.PC+1); \
+ if (PAGE_CROSS (Addr, Regs.XR)) { \
+ ++Cycles; \
+ } \
+ Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 3
+
+/* abs,y */
+#define AC_OP_ABSY(op) \
+ unsigned Addr; \
+ Cycles = 4; \
+ Addr = MemReadWord (Regs.PC+1); \
+ if (PAGE_CROSS (Addr, Regs.YR)) { \
+ ++Cycles; \
+ } \
+ Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 3
+
+/* (zp,x) */
+#define AC_OP_ZPXIND(op) \
+ unsigned char ZPAddr; \
+ unsigned Addr; \
+ Cycles = 6; \
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
+ Addr = MemReadZPWord (ZPAddr); \
+ Regs.AC = Regs.AC op MemReadByte (Addr); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 2
+
+/* (zp),y */
+#define AC_OP_ZPINDY(op) \
+ unsigned char ZPAddr; \
+ unsigned Addr; \
+ Cycles = 5; \
+ ZPAddr = MemReadByte (Regs.PC+1); \
+ Addr = MemReadZPWord (ZPAddr) + Regs.YR; \
+ Regs.AC = Regs.AC op MemReadByte (Addr); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ Regs.PC += 2
+
+/* ADC */
+#define ADC(v) \
+ do { \
+ unsigned old = Regs.AC; \
+ unsigned rhs = (v & 0xFF); \
+ if (GET_DF ()) { \
+ unsigned lo; \
+ int res; \
+ lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \
+ if (lo >= 0x0A) { \
+ lo = ((lo + 0x06) & 0x0F) + 0x10; \
+ } \
+ Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \
+ res = (signed char)(old & 0xF0) + \
+ (signed char)(rhs & 0xF0) + \
+ (signed char)lo; \
+ TEST_ZF (old + rhs + GET_CF ()); \
+ TEST_SF (Regs.AC); \
+ if (Regs.AC >= 0xA0) { \
+ Regs.AC += 0x60; \
+ } \
+ TEST_CF (Regs.AC); \
+ SET_OF ((res < -128) || (res > 127)); \
+ } else { \
+ Regs.AC += rhs + GET_CF (); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ TEST_CF (Regs.AC); \
+ SET_OF (!((old ^ rhs) & 0x80) && \
+ ((old ^ Regs.AC) & 0x80)); \
+ Regs.AC &= 0xFF; \
+ } \
+ } while (0)
+
+/* branches */
+#define BRANCH(cond) \
+ Cycles = 2; \
+ if (cond) { \
+ signed char Offs; \
+ unsigned char OldPCH; \
+ ++Cycles; \
+ Offs = (signed char) MemReadByte (Regs.PC+1); \
+ OldPCH = PCH; \
+ Regs.PC += 2 + (int) Offs; \
+ if (PCH != OldPCH) { \
+ ++Cycles; \
+ } \
+ } else { \
+ Regs.PC += 2; \
+ }
+
+/* compares */
+#define CMP(v1, v2) \
+ do { \
+ unsigned Result = v1 - v2; \
+ TEST_ZF (Result & 0xFF); \
+ TEST_SF (Result); \
+ SET_CF (Result <= 0xFF); \
+ } while (0)
+
+
+/* ROL */
+#define ROL(Val) \
+ Val <<= 1; \
+ if (GET_CF ()) { \
+ Val |= 0x01; \
+ } \
+ TEST_ZF (Val); \
+ TEST_SF (Val); \
+ TEST_CF (Val)
+
+/* ROR */
+#define ROR(Val) \
+ if (GET_CF ()) { \
+ Val |= 0x100; \
+ } \
+ SET_CF (Val & 0x01); \
+ Val >>= 1; \
+ TEST_ZF (Val); \
+ TEST_SF (Val)
+
+/* SBC */
+#define SBC(v) \
+ do { \
+ unsigned old = Regs.AC; \
+ unsigned rhs = (v & 0xFF); \
+ if (GET_DF ()) { \
+ unsigned lo; \
+ int res; \
+ lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \
+ if (lo & 0x80) { \
+ lo = ((lo - 0x06) & 0x0F) - 0x10; \
+ } \
+ Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \
+ if (Regs.AC & 0x80) { \
+ Regs.AC -= 0x60; \
+ } \
+ res = Regs.AC - rhs + (!GET_CF ()); \
+ TEST_ZF (res); \
+ TEST_SF (res); \
+ SET_CF (res <= 0xFF); \
+ SET_OF (((old^rhs) & (old^res) & 0x80)); \
+ } else { \
+ Regs.AC -= rhs - (!GET_CF ()); \
+ TEST_ZF (Regs.AC); \
+ TEST_SF (Regs.AC); \
+ SET_CF (Regs.AC <= 0xFF); \
+ SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \
+ Regs.AC &= 0xFF; \
+ } \
+ } while (0)
+
+
+
+/*****************************************************************************/
+/* Opcode handling functions */
+/*****************************************************************************/
+
+
+
+static void OPC_Illegal (void)
+{
+ Error ("Illegal opcode $%02X at address $%04X",
+ MemReadByte (Regs.PC), Regs.PC);
+}
+
+
+
+static void OPC_6502_00 (void)
+/* Opcode $00: BRK */
+{
+ Cycles = 7;
+ Regs.PC += 2;
+ SET_BF (1);
+ PUSH (PCH);
+ PUSH (PCL);
+ PUSH (Regs.SR);
+ SET_IF (1);
+ Regs.PC = MemReadWord (0xFFFE);
+}
+
+
+
+static void OPC_6502_01 (void)
+/* Opcode $01: ORA (ind,x) */
+{
+ AC_OP_ZPXIND (|);
+}
+
+
+
+static void OPC_6502_05 (void)
+/* Opcode $05: ORA zp */
+{
+ AC_OP_ZP (|);
+}
+
+
+
+static void OPC_6502_06 (void)
+/* Opcode $06: ASL zp */
+{
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (ZPAddr) << 1;
+ MemWriteByte (ZPAddr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_08 (void)
+/* Opcode $08: PHP */
+{
+ Cycles = 3;
+ PUSH (Regs.SR & ~BF);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_09 (void)
+/* Opcode $09: ORA #imm */
+{
+ AC_OP_IMM (|);
+}
+
+
+
+static void OPC_6502_0A (void)
+/* Opcode $0A: ASL a */
+{
+ Cycles = 2;
+ Regs.AC <<= 1;
+ TEST_ZF (Regs.AC & 0xFF);
+ TEST_SF (Regs.AC);
+ SET_CF (Regs.AC & 0x100);
+ Regs.AC &= 0xFF;
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_0D (void)
+/* Opcode $0D: ORA abs */
+{
+ AC_OP_ABS (|);
+}
+
+
+
+static void OPC_6502_0E (void)
+/* Opcode $0E: ALS abs */
+{
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 6;
+ Addr = MemReadWord (Regs.PC+1);
+ Val = MemReadByte (Addr) << 1;
+ MemWriteByte (Addr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_10 (void)
+/* Opcode $10: BPL */
+{
+ BRANCH (!GET_SF ());
+}
+
+
+
+static void OPC_6502_11 (void)
+/* Opcode $11: ORA (zp),y */
+{
+ AC_OP_ZPINDY (|);
+}
+
+
+
+static void OPC_6502_15 (void)
+/* Opcode $15: ORA zp,x */
+{
+ AC_OP_ZPX (|);
+}
+
+
+
+static void OPC_6502_16 (void)
+/* Opcode $16: ASL zp,x */
+{
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (ZPAddr) << 1;
+ MemWriteByte (ZPAddr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_18 (void)
+/* Opcode $18: CLC */
+{
+ Cycles = 2;
+ SET_CF (0);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_19 (void)
+/* Opcode $19: ORA abs,y */
+{
+ AC_OP_ABSY (|);
+}
+
+
+
+static void OPC_6502_1D (void)
+/* Opcode $1D: ORA abs,x */
+{
+ AC_OP_ABSX (|);
+}
+
+
+
+static void OPC_6502_1E (void)
+/* Opcode $1E: ASL abs,x */
+{
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 7;
+ Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (Addr) << 1;
+ MemWriteByte (Addr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_20 (void)
+/* Opcode $20: JSR */
+{
+ unsigned Addr;
+ Cycles = 6;
+ Addr = MemReadWord (Regs.PC+1);
+ Regs.PC += 2;
+ PUSH (PCH);
+ PUSH (PCL);
+ Regs.PC = Addr;
+
+ ParaVirtualization (&Regs);
+}
+
+
+
+static void OPC_6502_21 (void)
+/* Opcode $21: AND (zp,x) */
+{
+ AC_OP_ZPXIND (&);
+}
+
+
+
+static void OPC_6502_24 (void)
+/* Opcode $24: BIT zp */
+{
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (ZPAddr);
+ SET_SF (Val & 0x80);
+ SET_OF (Val & 0x40);
+ SET_ZF ((Val & Regs.AC) == 0);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_25 (void)
+/* Opcode $25: AND zp */
+{
+ AC_OP_ZP (&);
+}
+
+
+
+static void OPC_6502_26 (void)
+/* Opcode $26: ROL zp */
+{
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (ZPAddr);
+ ROL (Val);
+ MemWriteByte (ZPAddr, Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_28 (void)
+/* Opcode $28: PLP */
+{
+ Cycles = 4;
+ Regs.SR = (POP () & ~BF);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_29 (void)
+/* Opcode $29: AND #imm */
+{
+ AC_OP_IMM (&);
+}
+
+
+
+static void OPC_6502_2A (void)
+/* Opcode $2A: ROL a */
+{
+ Cycles = 2;
+ ROL (Regs.AC);
+ Regs.AC &= 0xFF;
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_2C (void)
+/* Opcode $2C: BIT abs */
+{
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 4;
+ Addr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (Addr);
+ SET_SF (Val & 0x80);
+ SET_OF (Val & 0x40);
+ SET_ZF ((Val & Regs.AC) == 0);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_2D (void)
+/* Opcode $2D: AND abs */
+{
+ AC_OP_ABS (&);
+}
+
+
+
+static void OPC_6502_2E (void)
+/* Opcode $2E: ROL abs */
+{
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 6;
+ Addr = MemReadWord (Regs.PC+1);
+ Val = MemReadByte (Addr);
+ ROL (Val);
+ MemWriteByte (Addr, Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_30 (void)
+/* Opcode $30: BMI */
+{
+ BRANCH (GET_SF ());
+}
+
+
+
+static void OPC_6502_31 (void)
+/* Opcode $31: AND (zp),y */
+{
+ AC_OP_ZPINDY (&);
+}
+
+
+
+static void OPC_6502_35 (void)
+/* Opcode $35: AND zp,x */
+{
+ AC_OP_ZPX (&);
+}
+
+
+
+static void OPC_6502_36 (void)
+/* Opcode $36: ROL zp,x */
+{
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (ZPAddr);
+ ROL (Val);
+ MemWriteByte (ZPAddr, Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_38 (void)
+/* Opcode $38: SEC */
+{
+ Cycles = 2;
+ SET_CF (1);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_39 (void)
+/* Opcode $39: AND abs,y */
+{
+ AC_OP_ABSY (&);
+}
+
+
+
+static void OPC_6502_3D (void)
+/* Opcode $3D: AND abs,x */
+{
+ AC_OP_ABSX (&);
+}
+
+
+
+static void OPC_6502_3E (void)
+/* Opcode $3E: ROL abs,x */
+{
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 7;
+ Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (Addr);
+ ROL (Val);
+ MemWriteByte (Addr, Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_40 (void)
+/* Opcode $40: RTI */
+{
+ Cycles = 6;
+ Regs.SR = POP ();
+ Regs.PC = POP (); /* PCL */
+ Regs.PC |= (POP () << 8); /* PCH */
+}
+
+
+
+static void OPC_6502_41 (void)
+/* Opcode $41: EOR (zp,x) */
+{
+ AC_OP_ZPXIND (^);
+}
+
+
+
+static void OPC_6502_45 (void)
+/* Opcode $45: EOR zp */
+{
+ AC_OP_ZP (^);
+}
+
+
+
+static void OPC_6502_46 (void)
+/* Opcode $46: LSR zp */
+{
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (ZPAddr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ MemWriteByte (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_48 (void)
+/* Opcode $48: PHA */
+{
+ Cycles = 3;
+ PUSH (Regs.AC);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_49 (void)
+/* Opcode $49: EOR #imm */
+{
+ AC_OP_IMM (^);
+}
+
+
+
+static void OPC_6502_4A (void)
+/* Opcode $4A: LSR a */
+{
+ Cycles = 2;
+ SET_CF (Regs.AC & 0x01);
+ Regs.AC >>= 1;
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_4C (void)
+/* Opcode $4C: JMP abs */
+{
+ Cycles = 3;
+ Regs.PC = MemReadWord (Regs.PC+1);
+
+ ParaVirtualization (&Regs);
+}
+
+
+
+static void OPC_6502_4D (void)
+/* Opcode $4D: EOR abs */
+{
+ AC_OP_ABS (^);
+}
+
+
+
+static void OPC_6502_4E (void)
+/* Opcode $4E: LSR abs */
+{
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 6;
+ Addr = MemReadWord (Regs.PC+1);
+ Val = MemReadByte (Addr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ MemWriteByte (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_50 (void)
+/* Opcode $50: BVC */
+{
+ BRANCH (!GET_OF ());
+}
+
+
+
+static void OPC_6502_51 (void)
+/* Opcode $51: EOR (zp),y */
+{
+ AC_OP_ZPINDY (^);
+}
+
+
+
+static void OPC_6502_55 (void)
+/* Opcode $55: EOR zp,x */
+{
+ AC_OP_ZPX (^);
+}
+
+
+
+static void OPC_6502_56 (void)
+/* Opcode $56: LSR zp,x */
+{
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (ZPAddr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ MemWriteByte (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_58 (void)
+/* Opcode $58: CLI */
+{
+ Cycles = 2;
+ SET_IF (0);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_59 (void)
+/* Opcode $59: EOR abs,y */
+{
+ AC_OP_ABSY (^);
+}
+
+
+
+static void OPC_6502_5D (void)
+/* Opcode $5D: EOR abs,x */
+{
+ AC_OP_ABSX (^);
+}
+
+
+
+static void OPC_6502_5E (void)
+/* Opcode $5E: LSR abs,x */
+{
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 7;
+ Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (Addr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ MemWriteByte (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_60 (void)
+/* Opcode $60: RTS */
+{
+ Cycles = 6;
+ Regs.PC = POP (); /* PCL */
+ Regs.PC |= (POP () << 8); /* PCH */
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_61 (void)
+/* Opcode $61: ADC (zp,x) */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Addr = MemReadZPWord (ZPAddr);
+ ADC (MemReadByte (Addr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_65 (void)
+/* Opcode $65: ADC zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ ADC (MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_66 (void)
+/* Opcode $66: ROR zp */
+{
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (ZPAddr);
+ ROR (Val);
+ MemWriteByte (ZPAddr, Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_68 (void)
+/* Opcode $68: PLA */
+{
+ Cycles = 4;
+ Regs.AC = POP ();
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_69 (void)
+/* Opcode $69: ADC #imm */
+{
+ Cycles = 2;
+ ADC (MemReadByte (Regs.PC+1));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_6A (void)
+/* Opcode $6A: ROR a */
+{
+ Cycles = 2;
+ ROR (Regs.AC);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_6C (void)
+/* Opcode $6C: JMP (ind) */
+{
+ unsigned PC, Lo, Hi;
+ Cycles = 5;
+ PC = Regs.PC;
+ Lo = MemReadWord (PC+1);
+
+ /* Emulate the 6502 bug */
+ Regs.PC = MemReadByte (Lo);
+ Hi = (Lo & 0xFF00) | ((Lo + 1) & 0xFF);
+ Regs.PC |= (MemReadByte (Hi) << 8);
+
+ /* Output a warning if the bug is triggered */
+ if (Hi != Lo + 1) {
+ Warning ("6502 indirect jump bug triggered at $%04X, ind addr = $%04X",
+ PC, Lo);
+ }
+}
+
+
+
+static void OPC_65C02_6C (void)
+/* Opcode $6C: JMP (ind) */
+{
+ /* 6502 bug fixed here */
+ Cycles = 5;
+ Regs.PC = MemReadWord (MemReadWord (Regs.PC+1));
+}
+
+
+
+static void OPC_6502_6D (void)
+/* Opcode $6D: ADC abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ ADC (MemReadByte (Addr));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_6E (void)
+/* Opcode $6E: ROR abs */
+{
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 6;
+ Addr = MemReadWord (Regs.PC+1);
+ Val = MemReadByte (Addr);
+ ROR (Val);
+ MemWriteByte (Addr, Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_70 (void)
+/* Opcode $70: BVS */
+{
+ BRANCH (GET_OF ());
+}
+
+
+
+static void OPC_6502_71 (void)
+/* Opcode $71: ADC (zp),y */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Addr = MemReadZPWord (ZPAddr);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ ADC (MemReadByte (Addr + Regs.YR));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_75 (void)
+/* Opcode $75: ADC zp,x */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ ADC (MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_76 (void)
+/* Opcode $76: ROR zp,x */
+{
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (ZPAddr);
+ ROR (Val);
+ MemWriteByte (ZPAddr, Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_78 (void)
+/* Opcode $78: SEI */
+{
+ Cycles = 2;
+ SET_IF (1);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_79 (void)
+/* Opcode $79: ADC abs,y */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ ADC (MemReadByte (Addr + Regs.YR));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_7D (void)
+/* Opcode $7D: ADC abs,x */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.XR)) {
+ ++Cycles;
+ }
+ ADC (MemReadByte (Addr + Regs.XR));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_7E (void)
+/* Opcode $7E: ROR abs,x */
+{
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 7;
+ Addr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (Addr);
+ ROR (Val);
+ MemWriteByte (Addr, Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_81 (void)
+/* Opcode $81: STA (zp,x) */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Addr = MemReadZPWord (ZPAddr);
+ MemWriteByte (Addr, Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_84 (void)
+/* Opcode $84: STY zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ MemWriteByte (ZPAddr, Regs.YR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_85 (void)
+/* Opcode $85: STA zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ MemWriteByte (ZPAddr, Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_86 (void)
+/* Opcode $86: STX zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ MemWriteByte (ZPAddr, Regs.XR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_88 (void)
+/* Opcode $88: DEY */
+{
+ Cycles = 2;
+ Regs.YR = (Regs.YR - 1) & 0xFF;
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_8A (void)
+/* Opcode $8A: TXA */
+{
+ Cycles = 2;
+ Regs.AC = Regs.XR;
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_8C (void)
+/* Opcode $8C: STY abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ MemWriteByte (Addr, Regs.YR);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_8D (void)
+/* Opcode $8D: STA abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ MemWriteByte (Addr, Regs.AC);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_8E (void)
+/* Opcode $8E: STX abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ MemWriteByte (Addr, Regs.XR);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_90 (void)
+/* Opcode $90: BCC */
+{
+ BRANCH (!GET_CF ());
+}
+
+
+
+static void OPC_6502_91 (void)
+/* Opcode $91: sta (zp),y */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Addr = MemReadZPWord (ZPAddr) + Regs.YR;
+ MemWriteByte (Addr, Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_94 (void)
+/* Opcode $94: STY zp,x */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ MemWriteByte (ZPAddr, Regs.YR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_95 (void)
+/* Opcode $95: STA zp,x */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ MemWriteByte (ZPAddr, Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_96 (void)
+/* Opcode $96: stx zp,y */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
+ MemWriteByte (ZPAddr, Regs.XR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_98 (void)
+/* Opcode $98: TYA */
+{
+ Cycles = 2;
+ Regs.AC = Regs.YR;
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_99 (void)
+/* Opcode $99: STA abs,y */
+{
+ unsigned Addr;
+ Cycles = 5;
+ Addr = MemReadWord (Regs.PC+1) + Regs.YR;
+ MemWriteByte (Addr, Regs.AC);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_9A (void)
+/* Opcode $9A: TXS */
+{
+ Cycles = 2;
+ Regs.SP = Regs.XR;
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_9D (void)
+/* Opcode $9D: STA abs,x */
+{
+ unsigned Addr;
+ Cycles = 5;
+ Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+ MemWriteByte (Addr, Regs.AC);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_A0 (void)
+/* Opcode $A0: LDY #imm */
+{
+ Cycles = 2;
+ Regs.YR = MemReadByte (Regs.PC+1);
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A1 (void)
+/* Opcode $A1: LDA (zp,x) */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Addr = MemReadZPWord (ZPAddr);
+ Regs.AC = MemReadByte (Addr);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A2 (void)
+/* Opcode $A2: LDX #imm */
+{
+ Cycles = 2;
+ Regs.XR = MemReadByte (Regs.PC+1);
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A4 (void)
+/* Opcode $A4: LDY zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Regs.YR = MemReadByte (ZPAddr);
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A5 (void)
+/* Opcode $A5: LDA zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Regs.AC = MemReadByte (ZPAddr);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A6 (void)
+/* Opcode $A6: LDX zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Regs.XR = MemReadByte (ZPAddr);
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A8 (void)
+/* Opcode $A8: TAY */
+{
+ Cycles = 2;
+ Regs.YR = Regs.AC;
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_A9 (void)
+/* Opcode $A9: LDA #imm */
+{
+ Cycles = 2;
+ Regs.AC = MemReadByte (Regs.PC+1);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_AA (void)
+/* Opcode $AA: TAX */
+{
+ Cycles = 2;
+ Regs.XR = Regs.AC;
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_AC (void)
+/* Opcode $Regs.AC: LDY abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ Regs.YR = MemReadByte (Addr);
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_AD (void)
+/* Opcode $AD: LDA abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ Regs.AC = MemReadByte (Addr);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_AE (void)
+/* Opcode $AE: LDX abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ Regs.XR = MemReadByte (Addr);
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_B0 (void)
+/* Opcode $B0: BCS */
+{
+ BRANCH (GET_CF ());
+}
+
+
+
+static void OPC_6502_B1 (void)
+/* Opcode $B1: LDA (zp),y */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Addr = MemReadZPWord (ZPAddr);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ Regs.AC = MemReadByte (Addr + Regs.YR);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B4 (void)
+/* Opcode $B4: LDY zp,x */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Regs.YR = MemReadByte (ZPAddr);
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B5 (void)
+/* Opcode $B5: LDA zp,x */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Regs.AC = MemReadByte (ZPAddr);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B6 (void)
+/* Opcode $B6: LDX zp,y */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
+ Regs.XR = MemReadByte (ZPAddr);
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B8 (void)
+/* Opcode $B8: CLV */
+{
+ Cycles = 2;
+ SET_OF (0);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_B9 (void)
+/* Opcode $B9: LDA abs,y */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ Regs.AC = MemReadByte (Addr + Regs.YR);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_BA (void)
+/* Opcode $BA: TSX */
+{
+ Cycles = 2;
+ Regs.XR = Regs.SP;
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_BC (void)
+/* Opcode $BC: LDY abs,x */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.XR)) {
+ ++Cycles;
+ }
+ Regs.YR = MemReadByte (Addr + Regs.XR);
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_BD (void)
+/* Opcode $BD: LDA abs,x */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.XR)) {
+ ++Cycles;
+ }
+ Regs.AC = MemReadByte (Addr + Regs.XR);
+ TEST_ZF (Regs.AC);
+ TEST_SF (Regs.AC);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_BE (void)
+/* Opcode $BE: LDX abs,y */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ Regs.XR = MemReadByte (Addr + Regs.YR);
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_C0 (void)
+/* Opcode $C0: CPY #imm */
+{
+ Cycles = 2;
+ CMP (Regs.YR, MemReadByte (Regs.PC+1));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C1 (void)
+/* Opcode $C1: CMP (zp,x) */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Addr = MemReadZPWord (ZPAddr);
+ CMP (Regs.AC, MemReadByte (Addr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C4 (void)
+/* Opcode $C4: CPY zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ CMP (Regs.YR, MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C5 (void)
+/* Opcode $C5: CMP zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ CMP (Regs.AC, MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C6 (void)
+/* Opcode $C6: DEC zp */
+{
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (ZPAddr) - 1;
+ MemWriteByte (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C8 (void)
+/* Opcode $C8: INY */
+{
+ Cycles = 2;
+ Regs.YR = (Regs.YR + 1) & 0xFF;
+ TEST_ZF (Regs.YR);
+ TEST_SF (Regs.YR);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_C9 (void)
+/* Opcode $C9: CMP #imm */
+{
+ Cycles = 2;
+ CMP (Regs.AC, MemReadByte (Regs.PC+1));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_CA (void)
+/* Opcode $CA: DEX */
+{
+ Cycles = 2;
+ Regs.XR = (Regs.XR - 1) & 0xFF;
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_CC (void)
+/* Opcode $CC: CPY abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ CMP (Regs.YR, MemReadByte (Addr));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_CD (void)
+/* Opcode $CD: CMP abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ CMP (Regs.AC, MemReadByte (Addr));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_CE (void)
+/* Opcode $CE: DEC abs */
+{
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 6;
+ Addr = MemReadWord (Regs.PC+1);
+ Val = MemReadByte (Addr) - 1;
+ MemWriteByte (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_D0 (void)
+/* Opcode $D0: BNE */
+{
+ BRANCH (!GET_ZF ());
+}
+
+
+
+static void OPC_6502_D1 (void)
+/* Opcode $D1: CMP (zp),y */
+{
+ unsigned ZPAddr;
+ unsigned Addr;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Addr = MemReadWord (ZPAddr);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_D5 (void)
+/* Opcode $D5: CMP zp,x */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ CMP (Regs.AC, MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_D6 (void)
+/* Opcode $D6: DEC zp,x */
+{
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (ZPAddr) - 1;
+ MemWriteByte (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_D8 (void)
+/* Opcode $D8: CLD */
+{
+ Cycles = 2;
+ SET_DF (0);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_D9 (void)
+/* Opcode $D9: CMP abs,y */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_DD (void)
+/* Opcode $DD: CMP abs,x */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.XR)) {
+ ++Cycles;
+ }
+ CMP (Regs.AC, MemReadByte (Addr + Regs.XR));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_DE (void)
+/* Opcode $DE: DEC abs,x */
+{
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 7;
+ Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (Addr) - 1;
+ MemWriteByte (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_E0 (void)
+/* Opcode $E0: CPX #imm */
+{
+ Cycles = 2;
+ CMP (Regs.XR, MemReadByte (Regs.PC+1));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E1 (void)
+/* Opcode $E1: SBC (zp,x) */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Addr = MemReadZPWord (ZPAddr);
+ SBC (MemReadByte (Addr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E4 (void)
+/* Opcode $E4: CPX zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ CMP (Regs.XR, MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E5 (void)
+/* Opcode $E5: SBC zp */
+{
+ unsigned char ZPAddr;
+ Cycles = 3;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ SBC (MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E6 (void)
+/* Opcode $E6: INC zp */
+{
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Val = MemReadByte (ZPAddr) + 1;
+ MemWriteByte (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E8 (void)
+/* Opcode $E8: INX */
+{
+ Cycles = 2;
+ Regs.XR = (Regs.XR + 1) & 0xFF;
+ TEST_ZF (Regs.XR);
+ TEST_SF (Regs.XR);
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_E9 (void)
+/* Opcode $E9: SBC #imm */
+{
+ Cycles = 2;
+ SBC (MemReadByte (Regs.PC+1));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_EA (void)
+/* Opcode $EA: NOP */
+{
+ /* This one is easy... */
+ Cycles = 2;
+ Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_EC (void)
+/* Opcode $EC: CPX abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ CMP (Regs.XR, MemReadByte (Addr));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_ED (void)
+/* Opcode $ED: SBC abs */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ SBC (MemReadByte (Addr));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_EE (void)
+/* Opcode $EE: INC abs */
+{
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 6;
+ Addr = MemReadWord (Regs.PC+1);
+ Val = MemReadByte (Addr) + 1;
+ MemWriteByte (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_F0 (void)
+/* Opcode $F0: BEQ */
+{
+ BRANCH (GET_ZF ());
+}
+
+
+
+static void OPC_6502_F1 (void)
+/* Opcode $F1: SBC (zp),y */
+{
+ unsigned char ZPAddr;
+ unsigned Addr;
+ Cycles = 5;
+ ZPAddr = MemReadByte (Regs.PC+1);
+ Addr = MemReadZPWord (ZPAddr);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ SBC (MemReadByte (Addr + Regs.YR));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_F5 (void)
+/* Opcode $F5: SBC zp,x */
+{
+ unsigned char ZPAddr;
+ Cycles = 4;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ SBC (MemReadByte (ZPAddr));
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_F6 (void)
+/* Opcode $F6: INC zp,x */
+{
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 6;
+ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (ZPAddr) + 1;
+ MemWriteByte (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_F8 (void)
+/* Opcode $F8: SED */
+{
+ SET_DF (1);
+}
+
+
+
+static void OPC_6502_F9 (void)
+/* Opcode $F9: SBC abs,y */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.YR)) {
+ ++Cycles;
+ }
+ SBC (MemReadByte (Addr + Regs.YR));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_FD (void)
+/* Opcode $FD: SBC abs,x */
+{
+ unsigned Addr;
+ Cycles = 4;
+ Addr = MemReadWord (Regs.PC+1);
+ if (PAGE_CROSS (Addr, Regs.XR)) {
+ ++Cycles;
+ }
+ SBC (MemReadByte (Addr + Regs.XR));
+ Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_FE (void)
+/* Opcode $FE: INC abs,x */
+{
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 7;
+ Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+ Val = MemReadByte (Addr) + 1;
+ MemWriteByte (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ Regs.PC += 3;
+}
+
+
+
+/*****************************************************************************/
+/* Opcode handler tables */
+/*****************************************************************************/
+
+
+
+/* Opcode handler table for the 6502 */
+static const OPFunc OP6502Table[256] = {
+ OPC_6502_00,
+ OPC_6502_01,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_05,
+ OPC_6502_06,
+ OPC_Illegal,
+ OPC_6502_08,
+ OPC_6502_09,
+ OPC_6502_0A,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_0D,
+ OPC_6502_0E,
+ OPC_Illegal,
+ OPC_6502_10,
+ OPC_6502_11,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_15,
+ OPC_6502_16,
+ OPC_Illegal,
+ OPC_6502_18,
+ OPC_6502_19,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_1D,
+ OPC_6502_1E,
+ OPC_Illegal,
+ OPC_6502_20,
+ OPC_6502_21,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_24,
+ OPC_6502_25,
+ OPC_6502_26,
+ OPC_Illegal,
+ OPC_6502_28,
+ OPC_6502_29,
+ OPC_6502_2A,
+ OPC_Illegal,
+ OPC_6502_2C,
+ OPC_6502_2D,
+ OPC_6502_2E,
+ OPC_Illegal,
+ OPC_6502_30,
+ OPC_6502_31,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_35,
+ OPC_6502_36,
+ OPC_Illegal,
+ OPC_6502_38,
+ OPC_6502_39,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_3D,
+ OPC_6502_3E,
+ OPC_Illegal,
+ OPC_6502_40,
+ OPC_6502_41,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_45,
+ OPC_6502_46,
+ OPC_Illegal,
+ OPC_6502_48,
+ OPC_6502_49,
+ OPC_6502_4A,
+ OPC_Illegal,
+ OPC_6502_4C,
+ OPC_6502_4D,
+ OPC_6502_4E,
+ OPC_Illegal,
+ OPC_6502_50,
+ OPC_6502_51,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_55,
+ OPC_6502_56,
+ OPC_Illegal,
+ OPC_6502_58,
+ OPC_6502_59,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_5D,
+ OPC_6502_5E,
+ OPC_Illegal,
+ OPC_6502_60,
+ OPC_6502_61,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_65,
+ OPC_6502_66,
+ OPC_Illegal,
+ OPC_6502_68,
+ OPC_6502_69,
+ OPC_6502_6A,
+ OPC_Illegal,
+ OPC_6502_6C,
+ OPC_6502_6D,
+ OPC_6502_6E,
+ OPC_Illegal,
+ OPC_6502_70,
+ OPC_6502_71,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_75,
+ OPC_6502_76,
+ OPC_Illegal,
+ OPC_6502_78,
+ OPC_6502_79,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_7D,
+ OPC_6502_7E,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_81,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_84,
+ OPC_6502_85,
+ OPC_6502_86,
+ OPC_Illegal,
+ OPC_6502_88,
+ OPC_Illegal,
+ OPC_6502_8A,
+ OPC_Illegal,
+ OPC_6502_8C,
+ OPC_6502_8D,
+ OPC_6502_8E,
+ OPC_Illegal,
+ OPC_6502_90,
+ OPC_6502_91,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_94,
+ OPC_6502_95,
+ OPC_6502_96,
+ OPC_Illegal,
+ OPC_6502_98,
+ OPC_6502_99,
+ OPC_6502_9A,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_9D,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_A0,
+ OPC_6502_A1,
+ OPC_6502_A2,
+ OPC_Illegal,
+ OPC_6502_A4,
+ OPC_6502_A5,
+ OPC_6502_A6,
+ OPC_Illegal,
+ OPC_6502_A8,
+ OPC_6502_A9,
+ OPC_6502_AA,
+ OPC_Illegal,
+ OPC_6502_AC,
+ OPC_6502_AD,
+ OPC_6502_AE,
+ OPC_Illegal,
+ OPC_6502_B0,
+ OPC_6502_B1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_B4,
+ OPC_6502_B5,
+ OPC_6502_B6,
+ OPC_Illegal,
+ OPC_6502_B8,
+ OPC_6502_B9,
+ OPC_6502_BA,
+ OPC_Illegal,
+ OPC_6502_BC,
+ OPC_6502_BD,
+ OPC_6502_BE,
+ OPC_Illegal,
+ OPC_6502_C0,
+ OPC_6502_C1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_C4,
+ OPC_6502_C5,
+ OPC_6502_C6,
+ OPC_Illegal,
+ OPC_6502_C8,
+ OPC_6502_C9,
+ OPC_6502_CA,
+ OPC_Illegal,
+ OPC_6502_CC,
+ OPC_6502_CD,
+ OPC_6502_CE,
+ OPC_Illegal,
+ OPC_6502_D0,
+ OPC_6502_D1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_D5,
+ OPC_6502_D6,
+ OPC_Illegal,
+ OPC_6502_D8,
+ OPC_6502_D9,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_DD,
+ OPC_6502_DE,
+ OPC_Illegal,
+ OPC_6502_E0,
+ OPC_6502_E1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_E4,
+ OPC_6502_E5,
+ OPC_6502_E6,
+ OPC_Illegal,
+ OPC_6502_E8,
+ OPC_6502_E9,
+ OPC_6502_EA,
+ OPC_Illegal,
+ OPC_6502_EC,
+ OPC_6502_ED,
+ OPC_6502_EE,
+ OPC_Illegal,
+ OPC_6502_F0,
+ OPC_6502_F1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_F5,
+ OPC_6502_F6,
+ OPC_Illegal,
+ OPC_6502_F8,
+ OPC_6502_F9,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_FD,
+ OPC_6502_FE,
+ OPC_Illegal,
+};
+
+
+
+/* Opcode handler table for the 65C02 */
+static const OPFunc OP65C02Table[256] = {
+ OPC_6502_00,
+ OPC_6502_01,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_05,
+ OPC_6502_06,
+ OPC_Illegal,
+ OPC_6502_08,
+ OPC_6502_09,
+ OPC_6502_0A,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_0D,
+ OPC_6502_0E,
+ OPC_Illegal,
+ OPC_6502_10,
+ OPC_6502_11,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_15,
+ OPC_6502_16,
+ OPC_Illegal,
+ OPC_6502_18,
+ OPC_6502_19,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_1D,
+ OPC_6502_1E,
+ OPC_Illegal,
+ OPC_6502_20,
+ OPC_6502_21,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_24,
+ OPC_6502_25,
+ OPC_6502_26,
+ OPC_Illegal,
+ OPC_6502_28,
+ OPC_6502_29,
+ OPC_6502_2A,
+ OPC_Illegal,
+ OPC_6502_2C,
+ OPC_6502_2D,
+ OPC_6502_2E,
+ OPC_Illegal,
+ OPC_6502_30,
+ OPC_6502_31,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_35,
+ OPC_6502_36,
+ OPC_Illegal,
+ OPC_6502_38,
+ OPC_6502_39,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_3D,
+ OPC_6502_3E,
+ OPC_Illegal,
+ OPC_6502_40,
+ OPC_6502_41,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_45,
+ OPC_6502_46,
+ OPC_Illegal,
+ OPC_6502_48,
+ OPC_6502_49,
+ OPC_6502_4A,
+ OPC_Illegal,
+ OPC_6502_4C,
+ OPC_6502_4D,
+ OPC_6502_4E,
+ OPC_Illegal,
+ OPC_6502_50,
+ OPC_6502_51,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_55,
+ OPC_6502_56,
+ OPC_Illegal,
+ OPC_6502_58,
+ OPC_6502_59,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_5D,
+ OPC_6502_5E,
+ OPC_Illegal,
+ OPC_6502_60,
+ OPC_6502_61,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_65,
+ OPC_6502_66,
+ OPC_Illegal,
+ OPC_6502_68,
+ OPC_6502_69,
+ OPC_6502_6A,
+ OPC_Illegal,
+ OPC_65C02_6C,
+ OPC_6502_6D,
+ OPC_6502_6E,
+ OPC_Illegal,
+ OPC_6502_70,
+ OPC_6502_71,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_75,
+ OPC_6502_76,
+ OPC_Illegal,
+ OPC_6502_78,
+ OPC_6502_79,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_7D,
+ OPC_6502_7E,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_81,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_84,
+ OPC_6502_85,
+ OPC_6502_86,
+ OPC_Illegal,
+ OPC_6502_88,
+ OPC_Illegal,
+ OPC_6502_8A,
+ OPC_Illegal,
+ OPC_6502_8C,
+ OPC_6502_8D,
+ OPC_6502_8E,
+ OPC_Illegal,
+ OPC_6502_90,
+ OPC_6502_91,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_94,
+ OPC_6502_95,
+ OPC_6502_96,
+ OPC_Illegal,
+ OPC_6502_98,
+ OPC_6502_99,
+ OPC_6502_9A,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_9D,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_A0,
+ OPC_6502_A1,
+ OPC_6502_A2,
+ OPC_Illegal,
+ OPC_6502_A4,
+ OPC_6502_A5,
+ OPC_6502_A6,
+ OPC_Illegal,
+ OPC_6502_A8,
+ OPC_6502_A9,
+ OPC_6502_AA,
+ OPC_Illegal,
+ OPC_6502_AC,
+ OPC_6502_AD,
+ OPC_6502_AE,
+ OPC_Illegal,
+ OPC_6502_B0,
+ OPC_6502_B1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_B4,
+ OPC_6502_B5,
+ OPC_6502_B6,
+ OPC_Illegal,
+ OPC_6502_B8,
+ OPC_6502_B9,
+ OPC_6502_BA,
+ OPC_Illegal,
+ OPC_6502_BC,
+ OPC_6502_BD,
+ OPC_6502_BE,
+ OPC_Illegal,
+ OPC_6502_C0,
+ OPC_6502_C1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_C4,
+ OPC_6502_C5,
+ OPC_6502_C6,
+ OPC_Illegal,
+ OPC_6502_C8,
+ OPC_6502_C9,
+ OPC_6502_CA,
+ OPC_Illegal,
+ OPC_6502_CC,
+ OPC_6502_CD,
+ OPC_6502_CE,
+ OPC_Illegal,
+ OPC_6502_D0,
+ OPC_6502_D1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_D5,
+ OPC_6502_D6,
+ OPC_Illegal,
+ OPC_6502_D8,
+ OPC_6502_D9,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_DD,
+ OPC_6502_DE,
+ OPC_Illegal,
+ OPC_6502_E0,
+ OPC_6502_E1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_E4,
+ OPC_6502_E5,
+ OPC_6502_E6,
+ OPC_Illegal,
+ OPC_6502_E8,
+ OPC_6502_E9,
+ OPC_6502_EA,
+ OPC_Illegal,
+ OPC_6502_EC,
+ OPC_6502_ED,
+ OPC_6502_EE,
+ OPC_Illegal,
+ OPC_6502_F0,
+ OPC_6502_F1,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_F5,
+ OPC_6502_F6,
+ OPC_Illegal,
+ OPC_6502_F8,
+ OPC_6502_F9,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_Illegal,
+ OPC_6502_FD,
+ OPC_6502_FE,
+ OPC_Illegal,
+};
+
+
+
+/* Tables with opcode handlers */
+static const OPFunc* Handlers[2] = {OP6502Table, OP65C02Table};
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void IRQRequest (void)
+/* Generate an IRQ */
+{
+ /* Remember the request */
+ HaveIRQRequest = 1;
+}
+
+
+
+void NMIRequest (void)
+/* Generate an NMI */
+{
+ /* Remember the request */
+ HaveNMIRequest = 1;
+}
+
+
+
+void Reset (void)
+/* Generate a CPU RESET */
+{
+ /* Reset the CPU */
+ HaveIRQRequest = 0;
+ HaveNMIRequest = 0;
+ Regs.SR = 0;
+ Regs.PC = MemReadWord (0xFFFC);
+}
+
+
+
+unsigned ExecuteInsn (void)
+/* Execute one CPU instruction */
+{
+ /* If we have an NMI request, handle it */
+ if (HaveNMIRequest) {
+
+ HaveNMIRequest = 0;
+ PUSH (PCH);
+ PUSH (PCL);
+ PUSH (Regs.SR);
+ SET_IF (1);
+ Regs.PC = MemReadWord (0xFFFA);
+ Cycles = 7;
+
+ } else if (HaveIRQRequest && GET_IF () == 0) {
+
+ HaveIRQRequest = 0;
+ PUSH (PCH);
+ PUSH (PCL);
+ PUSH (Regs.SR);
+ SET_IF (1);
+ Regs.PC = MemReadWord (0xFFFE);
+ Cycles = 7;
+
+ } else {
+
+ /* Normal instruction - read the next opcode */
+ unsigned char OPC = MemReadByte (Regs.PC);
+
+ /* Execute it */
+ Handlers[CPU][OPC] ();
+ }
+
+ /* Count cycles */
+ TotalCycles += Cycles;
+
+ /* Return the number of clock cycles needed by this insn */
+ return Cycles;
+}
+
+
+
+unsigned long GetCycles (void)
+/* Return the total number of cycles executed */
+{
+ /* Return the total number of cycles */
+ return TotalCycles;
+}
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 6502.h */
+/* */
+/* CPU core for the 6502 */
+/* */
+/* */
+/* */
+/* (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 _6502_H
+#define _6502_H
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Supported CPUs */
+typedef enum CPUType {
+ CPU_6502,
+ CPU_65C02
+} CPUType;
+
+/* 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 */
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void Reset (void);
+/* Generate a CPU RESET */
+
+void IRQRequest (void);
+/* Generate an IRQ */
+
+void NMIRequest (void);
+/* Generate an NMI */
+
+unsigned ExecuteInsn (void);
+/* Execute one CPU instruction. Return the number of clock cycles for the
+ * executed instruction.
+ */
+
+unsigned long GetCycles (void);
+/* Return the total number of clock cycles executed */
+
+
+
+/* End of 6502.h */
+
+#endif
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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];
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* addrspace.h */
-/* */
-/* CPU address space for the 6502 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 ADDRSPACE_H
-#define ADDRSPACE_H
-
-
-
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-/* Forwards */
-struct CPUData;
-struct ChipInstance;
-
-/* 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! */
-
-};
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-AddressSpace* NewAddressSpace (unsigned Size);
-/* Allocate a new address space and return it */
-
-void ASWrite (AddressSpace* AS, unsigned Addr, unsigned char Val);
-/* Write a byte to a given location */
-
-unsigned char ASRead (AddressSpace* AS, unsigned Addr);
-/* Read a byte from a location */
-
-void ASWriteCtrl (AddressSpace* AS, unsigned Addr, unsigned char Val);
-/* Write a byte to a given location */
-
-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). */
-
-
-
-/* End of addrspace.h */
-
-#endif
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
-
- }
- }
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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);
- }
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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, "");
-
-}
-
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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);
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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];
-}
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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];
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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];
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
- }
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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 ();
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* config.h */
-/* */
-/* Configuration file parsing for the sim65 6502 simulator */
-/* */
-/* */
-/* */
-/* (C) 1998-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 CONFIG_H
-#define CONFIG_H
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-void CfgRead (void);
-/* Read the configuration */
-
-
-
-/* End of config.h */
-
-#endif
-
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 6502.c */
-/* */
-/* CPU core for the 6502 */
-/* */
-/* */
-/* */
-/* (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 <stdarg.h>
-
-/* common */
-#include "abend.h"
-#include "attrib.h"
-#include "print.h"
-#include "strbuf.h"
-
-/* sim65 */
-#include "cpuif.h"
-
-
-
-/*****************************************************************************/
-/* Forwards */
-/*****************************************************************************/
-
-
-
-static void Init (const SimData* D);
-/* Initialize the module */
-
-static void* Create6502Instance (void* CfgInfo);
-/* Create an instance of a 6502 CPU */
-
-static void* Create65C02Instance (void* CfgInfo);
-/* Create an instance of a 65C02 CPU */
-
-static void DestroyInstance (void* Instance);
-/* Destroy an instance of a CPU */
-
-static void IRQRequest (void* Data);
-/* Generate an IRQ */
-
-static void NMIRequest (void* Data);
-/* Generate an NMI */
-
-static void Reset (void* Data);
-/* Generate a CPU RESET */
-
-static unsigned ExecuteInsn (void* Data);
-/* Execute one CPU instruction */
-
-static unsigned long GetCycles (void* Data);
-/* Return the total number of cycles executed */
-
-
-
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-/* The SimData pointer we get when InitChip is called */
-static const SimData* Sim;
-
-/* 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 */
-
-/* Type of an opcode handler function */
-struct CPUInstance;
-typedef void (*OPFunc) (struct CPUInstance* D);
-
-
-
-/* Control data passed to the main program */
-static const struct CPUData CData[] = {
- {
- "6502", /* Name of the CPU */
- CPUDATA_VER_MAJOR, /* Version information */
- CPUDATA_VER_MINOR,
-
- /* -- Exported functions -- */
- Init,
- Create6502Instance,
- DestroyInstance,
- Reset,
- IRQRequest,
- NMIRequest,
- ExecuteInsn,
- GetCycles
- },{
- "65C02", /* Name of the CPU */
- CPUDATA_VER_MAJOR, /* Version information */
- CPUDATA_VER_MINOR,
-
- /* -- Exported functions -- */
- Init,
- Create65C02Instance,
- DestroyInstance,
- Reset,
- IRQRequest,
- NMIRequest,
- ExecuteInsn,
- GetCycles
- },
-};
-
-
-/* CPU instance data */
-typedef struct CPUInstance CPUInstance;
-struct CPUInstance {
- const OPFunc* Handlers; /* Table with opcode handlers */
-
- CPURegs Regs; /* The CPU registers */
-
- unsigned Cycles; /* Cycles for the current insn */
- unsigned long TotalCycles; /* Total number of CPU cycles exec'd */
-
- unsigned StackPage; /* Allows to move the stack page */
-
- unsigned HaveNMIRequest; /* NMI request active */
- unsigned HaveIRQRequest; /* IRQ request active */
- unsigned CPUHalted; /* CPU is halted */
-};
-
-
-/*****************************************************************************/
-/* Helper functions and macros */
-/*****************************************************************************/
-
-
-
-/* Return the flags as a boolean value (0/1) */
-#define GET_CF() ((D->Regs.SR & CF) != 0)
-#define GET_ZF() ((D->Regs.SR & ZF) != 0)
-#define GET_IF() ((D->Regs.SR & IF) != 0)
-#define GET_DF() ((D->Regs.SR & DF) != 0)
-#define GET_BF() ((D->Regs.SR & BF) != 0)
-#define GET_OF() ((D->Regs.SR & OF) != 0)
-#define GET_SF() ((D->Regs.SR & SF) != 0)
-
-/* Set the flags. The parameter is a boolean flag that says if the flag should be
- * set or reset.
- */
-#define SET_CF(f) do { if (f) { D->Regs.SR |= CF; } else { D->Regs.SR &= ~CF; } } while (0)
-#define SET_ZF(f) do { if (f) { D->Regs.SR |= ZF; } else { D->Regs.SR &= ~ZF; } } while (0)
-#define SET_IF(f) do { if (f) { D->Regs.SR |= IF; } else { D->Regs.SR &= ~IF; } } while (0)
-#define SET_DF(f) do { if (f) { D->Regs.SR |= DF; } else { D->Regs.SR &= ~DF; } } while (0)
-#define SET_BF(f) do { if (f) { D->Regs.SR |= BF; } else { D->Regs.SR &= ~BF; } } while (0)
-#define SET_OF(f) do { if (f) { D->Regs.SR |= OF; } else { D->Regs.SR &= ~OF; } } while (0)
-#define SET_SF(f) do { if (f) { D->Regs.SR |= SF; } else { D->Regs.SR &= ~SF; } } while (0)
-
-/* Special test and set macros. The meaning of the parameter depends on the
- * actual flag that should be set or reset.
- */
-#define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
-#define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
-#define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
-
-/* Program counter halves */
-#define PCL (D->Regs.PC & 0xFF)
-#define PCH ((D->Regs.PC >> 8) & 0xFF)
-
-/* Stack operations */
-#define PUSH(Val) MemWriteByte (D->StackPage + D->Regs.SP--, Val)
-#define POP() MemReadByte (D->StackPage + ++D->Regs.SP)
-
-/* Test for page cross */
-#define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
-
-/* #imm */
-#define AC_OP_IMM(op) \
- D->Cycles = 2; \
- D->Regs.AC = D->Regs.AC op MemReadByte (D->Regs.PC+1); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 2
-
-/* zp */
-#define AC_OP_ZP(op) \
- D->Cycles = 3; \
- D->Regs.AC = D->Regs.AC op MemReadByte (MemReadByte (D->Regs.PC+1));\
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 2
-
-/* zp,x */
-#define AC_OP_ZPX(op) \
- unsigned char ZPAddr; \
- D->Cycles = 4; \
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR; \
- D->Regs.AC = D->Regs.AC op MemReadByte (ZPAddr); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 2
-
-/* zp,y */
-#define AC_OP_ZPY(op) \
- unsigned char ZPAddr; \
- D->Cycles = 4; \
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.YR; \
- D->Regs.AC = D->Regs.AC op MemReadByte (ZPAddr); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 2
-
-/* abs */
-#define AC_OP_ABS(op) \
- unsigned Addr; \
- D->Cycles = 4; \
- Addr = MemReadWord (D->Regs.PC+1); \
- D->Regs.AC = D->Regs.AC op MemReadByte (Addr); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 3
-
-/* abs,x */
-#define AC_OP_ABSX(op) \
- unsigned Addr; \
- D->Cycles = 4; \
- Addr = MemReadWord (D->Regs.PC+1); \
- if (PAGE_CROSS (Addr, D->Regs.XR)) { \
- ++D->Cycles; \
- } \
- D->Regs.AC = D->Regs.AC op MemReadByte (Addr + D->Regs.XR); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 3
-
-/* abs,y */
-#define AC_OP_ABSY(op) \
- unsigned Addr; \
- D->Cycles = 4; \
- Addr = MemReadWord (D->Regs.PC+1); \
- if (PAGE_CROSS (Addr, D->Regs.YR)) { \
- ++D->Cycles; \
- } \
- D->Regs.AC = D->Regs.AC op MemReadByte (Addr + D->Regs.YR); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 3
-
-/* (zp,x) */
-#define AC_OP_ZPXIND(op) \
- unsigned char ZPAddr; \
- unsigned Addr; \
- D->Cycles = 6; \
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR; \
- Addr = MemReadZPWord (ZPAddr); \
- D->Regs.AC = D->Regs.AC op MemReadByte (Addr); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 2
-
-/* (zp),y */
-#define AC_OP_ZPINDY(op) \
- unsigned char ZPAddr; \
- unsigned Addr; \
- D->Cycles = 5; \
- ZPAddr = MemReadByte (D->Regs.PC+1); \
- Addr = MemReadZPWord (ZPAddr) + D->Regs.YR; \
- D->Regs.AC = D->Regs.AC op MemReadByte (Addr); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- D->Regs.PC += 2
-
-/* ADC */
-#define ADC(v) \
- do { \
- unsigned old = D->Regs.AC; \
- unsigned rhs = (v & 0xFF); \
- if (GET_DF ()) { \
- unsigned lo; \
- int res; \
- lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \
- if (lo >= 0x0A) { \
- lo = ((lo + 0x06) & 0x0F) + 0x10; \
- } \
- D->Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \
- res = (signed char)(old & 0xF0) + \
- (signed char)(rhs & 0xF0) + \
- (signed char)lo; \
- TEST_ZF (old + rhs + GET_CF ()); \
- TEST_SF (D->Regs.AC); \
- if (D->Regs.AC >= 0xA0) { \
- D->Regs.AC += 0x60; \
- } \
- TEST_CF (D->Regs.AC); \
- SET_OF ((res < -128) || (res > 127)); \
- } else { \
- D->Regs.AC += rhs + GET_CF (); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- TEST_CF (D->Regs.AC); \
- SET_OF (!((old ^ rhs) & 0x80) && \
- ((old ^ D->Regs.AC) & 0x80)); \
- D->Regs.AC &= 0xFF; \
- } \
- } while (0)
-
-/* branches */
-#define BRANCH(cond) \
- D->Cycles = 2; \
- if (cond) { \
- signed char Offs; \
- unsigned char OldPCH; \
- ++D->Cycles; \
- Offs = (signed char) MemReadByte (D->Regs.PC+1); \
- OldPCH = PCH; \
- D->Regs.PC += 2 + (int) Offs; \
- if (PCH != OldPCH) { \
- ++D->Cycles; \
- } \
- } else { \
- D->Regs.PC += 2; \
- }
-
-/* compares */
-#define CMP(v1, v2) \
- do { \
- unsigned Result = v1 - v2; \
- TEST_ZF (Result & 0xFF); \
- TEST_SF (Result); \
- SET_CF (Result <= 0xFF); \
- } while (0)
-
-
-/* ROL */
-#define ROL(Val) \
- Val <<= 1; \
- if (GET_CF ()) { \
- Val |= 0x01; \
- } \
- TEST_ZF (Val); \
- TEST_SF (Val); \
- TEST_CF (Val)
-
-/* ROR */
-#define ROR(Val) \
- if (GET_CF ()) { \
- Val |= 0x100; \
- } \
- SET_CF (Val & 0x01); \
- Val >>= 1; \
- TEST_ZF (Val); \
- TEST_SF (Val)
-
-/* SBC */
-#define SBC(v) \
- do { \
- unsigned old = D->Regs.AC; \
- unsigned rhs = (v & 0xFF); \
- if (GET_DF ()) { \
- unsigned lo; \
- int res; \
- lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \
- if (lo & 0x80) { \
- lo = ((lo - 0x06) & 0x0F) - 0x10; \
- } \
- D->Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \
- if (D->Regs.AC & 0x80) { \
- D->Regs.AC -= 0x60; \
- } \
- res = D->Regs.AC - rhs + (!GET_CF ()); \
- TEST_ZF (res); \
- TEST_SF (res); \
- SET_CF (res <= 0xFF); \
- SET_OF (((old^rhs) & (old^res) & 0x80)); \
- } else { \
- D->Regs.AC -= rhs - (!GET_CF ()); \
- TEST_ZF (D->Regs.AC); \
- TEST_SF (D->Regs.AC); \
- SET_CF (D->Regs.AC <= 0xFF); \
- SET_OF (((old^rhs) & (old^D->Regs.AC) & 0x80)); \
- D->Regs.AC &= 0xFF; \
- } \
- } while (0)
-
-
-
-static unsigned char MemReadByte (unsigned Addr)
-/* Read a byte from a memory location */
-{
- return Sim->Read (Addr);
-}
-
-
-
-static unsigned MemReadWord (unsigned Addr)
-/* Read a word from a memory location */
-{
- unsigned W = Sim->Read (Addr);
- return (W | (Sim->Read (Addr + 1) << 8));
-}
-
-
-
-static unsigned MemReadZPWord (unsigned Addr)
-/* Read a word from the zero page. This function differs from ReadMemW in that
- * the read will always be in the zero page, even in case of an address
- * overflow.
- */
-{
- unsigned W = Sim->Read (Addr & 0xFF);
- return (W | (Sim->Read ((Addr + 1) & 0xFF) << 8));
-}
-
-
-
-static void MemWriteByte (unsigned Addr, unsigned char Val)
-/* Write a byte to a memory location */
-{
- Sim->Write (Addr, Val);
-}
-
-
-
-/*****************************************************************************/
-/* CPUInstance */
-/*****************************************************************************/
-
-
-
-static CPUInstance* NewCPUInstance (const OPFunc FuncTable[256], void* CfgInfo)
-/* Create and return a new CPU instance struct */
-{
- /* Allocate memory */
- CPUInstance* D = Sim->Malloc (sizeof (*D));
-
- /* Initialize the fields */
- D->Handlers = FuncTable; /* Table with opcode handlers */
- D->StackPage = 0x100; /* Allows to move the stack page */
- D->HaveNMIRequest = 0; /* NMI request active */
- D->HaveIRQRequest = 0; /* IRQ request active */
- D->CPUHalted = 0; /* CPU is halted */
-
- /* Return the new struct */
- return D;
-}
-
-
-
-static void DeleteCPUInstance (CPUInstance* Instance)
-/* Delete a CPU instance */
-{
- /* Just free the memory */
- Sim->Free (Instance);
-}
-
-
-
-/*****************************************************************************/
-/* Opcode handling functions */
-/*****************************************************************************/
-
-
-
-static void OPC_Illegal (CPUInstance* D)
-{
- Sim->Warning ("Illegal opcode $%02X at address $%04X\n",
- MemReadByte (D->Regs.PC), D->Regs.PC);
-}
-
-
-
-static void OPC_6502_00 (CPUInstance* D)
-/* Opcode $00: BRK */
-{
- D->Cycles = 7;
- D->Regs.PC += 2;
- SET_BF (1);
- PUSH (PCH);
- PUSH (PCL);
- PUSH (D->Regs.SR);
- SET_IF (1);
- D->Regs.PC = MemReadWord (0xFFFE);
-}
-
-
-
-static void OPC_6502_01 (CPUInstance* D)
-/* Opcode $01: ORA (ind,x) */
-{
- AC_OP_ZPXIND (|);
-}
-
-
-
-static void OPC_6502_05 (CPUInstance* D)
-/* Opcode $05: ORA zp */
-{
- AC_OP_ZP (|);
-}
-
-
-
-static void OPC_6502_06 (CPUInstance* D)
-/* Opcode $06: ASL zp */
-{
- unsigned char ZPAddr;
- unsigned Val;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (ZPAddr) << 1;
- MemWriteByte (ZPAddr, (unsigned char) Val);
- TEST_ZF (Val & 0xFF);
- TEST_SF (Val);
- SET_CF (Val & 0x100);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_08 (CPUInstance* D)
-/* Opcode $08: PHP */
-{
- D->Cycles = 3;
- PUSH (D->Regs.SR & ~BF);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_09 (CPUInstance* D)
-/* Opcode $09: ORA #imm */
-{
- AC_OP_IMM (|);
-}
-
-
-
-static void OPC_6502_0A (CPUInstance* D)
-/* Opcode $0A: ASL a */
-{
- D->Cycles = 2;
- D->Regs.AC <<= 1;
- TEST_ZF (D->Regs.AC & 0xFF);
- TEST_SF (D->Regs.AC);
- SET_CF (D->Regs.AC & 0x100);
- D->Regs.AC &= 0xFF;
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_0D (CPUInstance* D)
-/* Opcode $0D: ORA abs */
-{
- AC_OP_ABS (|);
-}
-
-
-
-static void OPC_6502_0E (CPUInstance* D)
-/* Opcode $0E: ALS abs */
-{
- unsigned Addr;
- unsigned Val;
- D->Cycles = 6;
- Addr = MemReadWord (D->Regs.PC+1);
- Val = MemReadByte (Addr) << 1;
- MemWriteByte (Addr, (unsigned char) Val);
- TEST_ZF (Val & 0xFF);
- TEST_SF (Val);
- SET_CF (Val & 0x100);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_10 (CPUInstance* D)
-/* Opcode $10: BPL */
-{
- BRANCH (!GET_SF ());
-}
-
-
-
-static void OPC_6502_11 (CPUInstance* D)
-/* Opcode $11: ORA (zp),y */
-{
- AC_OP_ZPINDY (|);
-}
-
-
-
-static void OPC_6502_15 (CPUInstance* D)
-/* Opcode $15: ORA zp,x */
-{
- AC_OP_ZPX (|);
-}
-
-
-
-static void OPC_6502_16 (CPUInstance* D)
-/* Opcode $16: ASL zp,x */
-{
- unsigned char ZPAddr;
- unsigned Val;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (ZPAddr) << 1;
- MemWriteByte (ZPAddr, (unsigned char) Val);
- TEST_ZF (Val & 0xFF);
- TEST_SF (Val);
- SET_CF (Val & 0x100);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_18 (CPUInstance* D)
-/* Opcode $18: CLC */
-{
- D->Cycles = 2;
- SET_CF (0);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_19 (CPUInstance* D)
-/* Opcode $19: ORA abs,y */
-{
- AC_OP_ABSY (|);
-}
-
-
-
-static void OPC_6502_1D (CPUInstance* D)
-/* Opcode $1D: ORA abs,x */
-{
- AC_OP_ABSX (|);
-}
-
-
-
-static void OPC_6502_1E (CPUInstance* D)
-/* Opcode $1E: ASL abs,x */
-{
- unsigned Addr;
- unsigned Val;
- D->Cycles = 7;
- Addr = MemReadWord (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (Addr) << 1;
- MemWriteByte (Addr, (unsigned char) Val);
- TEST_ZF (Val & 0xFF);
- TEST_SF (Val);
- SET_CF (Val & 0x100);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_20 (CPUInstance* D)
-/* Opcode $20: JSR */
-{
- unsigned Addr;
- D->Cycles = 6;
- Addr = MemReadWord (D->Regs.PC+1);
- D->Regs.PC += 2;
- PUSH (PCH);
- PUSH (PCL);
- D->Regs.PC = Addr;
-}
-
-
-
-static void OPC_6502_21 (CPUInstance* D)
-/* Opcode $21: AND (zp,x) */
-{
- AC_OP_ZPXIND (&);
-}
-
-
-
-static void OPC_6502_24 (CPUInstance* D)
-/* Opcode $24: BIT zp */
-{
- unsigned char ZPAddr;
- unsigned char Val;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (ZPAddr);
- SET_SF (Val & 0x80);
- SET_OF (Val & 0x40);
- SET_ZF ((Val & D->Regs.AC) == 0);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_25 (CPUInstance* D)
-/* Opcode $25: AND zp */
-{
- AC_OP_ZP (&);
-}
-
-
-
-static void OPC_6502_26 (CPUInstance* D)
-/* Opcode $26: ROL zp */
-{
- unsigned char ZPAddr;
- unsigned Val;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (ZPAddr);
- ROL (Val);
- MemWriteByte (ZPAddr, Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_28 (CPUInstance* D)
-/* Opcode $28: PLP */
-{
- D->Cycles = 4;
- D->Regs.SR = (POP () & ~BF);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_29 (CPUInstance* D)
-/* Opcode $29: AND #imm */
-{
- AC_OP_IMM (&);
-}
-
-
-
-static void OPC_6502_2A (CPUInstance* D)
-/* Opcode $2A: ROL a */
-{
- D->Cycles = 2;
- ROL (D->Regs.AC);
- D->Regs.AC &= 0xFF;
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_2C (CPUInstance* D)
-/* Opcode $2C: BIT abs */
-{
- unsigned Addr;
- unsigned char Val;
- D->Cycles = 4;
- Addr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (Addr);
- SET_SF (Val & 0x80);
- SET_OF (Val & 0x40);
- SET_ZF ((Val & D->Regs.AC) == 0);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_2D (CPUInstance* D)
-/* Opcode $2D: AND abs */
-{
- AC_OP_ABS (&);
-}
-
-
-
-static void OPC_6502_2E (CPUInstance* D)
-/* Opcode $2E: ROL abs */
-{
- unsigned Addr;
- unsigned Val;
- D->Cycles = 6;
- Addr = MemReadWord (D->Regs.PC+1);
- Val = MemReadByte (Addr);
- ROL (Val);
- MemWriteByte (Addr, Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_30 (CPUInstance* D)
-/* Opcode $30: BMI */
-{
- BRANCH (GET_SF ());
-}
-
-
-
-static void OPC_6502_31 (CPUInstance* D)
-/* Opcode $31: AND (zp),y */
-{
- AC_OP_ZPINDY (&);
-}
-
-
-
-static void OPC_6502_35 (CPUInstance* D)
-/* Opcode $35: AND zp,x */
-{
- AC_OP_ZPX (&);
-}
-
-
-
-static void OPC_6502_36 (CPUInstance* D)
-/* Opcode $36: ROL zp,x */
-{
- unsigned char ZPAddr;
- unsigned Val;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (ZPAddr);
- ROL (Val);
- MemWriteByte (ZPAddr, Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_38 (CPUInstance* D)
-/* Opcode $38: SEC */
-{
- D->Cycles = 2;
- SET_CF (1);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_39 (CPUInstance* D)
-/* Opcode $39: AND abs,y */
-{
- AC_OP_ABSY (&);
-}
-
-
-
-static void OPC_6502_3D (CPUInstance* D)
-/* Opcode $3D: AND abs,x */
-{
- AC_OP_ABSX (&);
-}
-
-
-
-static void OPC_6502_3E (CPUInstance* D)
-/* Opcode $3E: ROL abs,x */
-{
- unsigned Addr;
- unsigned Val;
- D->Cycles = 7;
- Addr = MemReadWord (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (Addr);
- ROL (Val);
- MemWriteByte (Addr, Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_40 (CPUInstance* D)
-/* Opcode $40: RTI */
-{
- D->Cycles = 6;
- D->Regs.SR = POP ();
- D->Regs.PC = POP (); /* PCL */
- D->Regs.PC |= (POP () << 8); /* PCH */
-}
-
-
-
-static void OPC_6502_41 (CPUInstance* D)
-/* Opcode $41: EOR (zp,x) */
-{
- AC_OP_ZPXIND (^);
-}
-
-
-
-static void OPC_6502_45 (CPUInstance* D)
-/* Opcode $45: EOR zp */
-{
- AC_OP_ZP (^);
-}
-
-
-
-static void OPC_6502_46 (CPUInstance* D)
-/* Opcode $46: LSR zp */
-{
- unsigned char ZPAddr;
- unsigned char Val;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (ZPAddr);
- SET_CF (Val & 0x01);
- Val >>= 1;
- MemWriteByte (ZPAddr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_48 (CPUInstance* D)
-/* Opcode $48: PHA */
-{
- D->Cycles = 3;
- PUSH (D->Regs.AC);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_49 (CPUInstance* D)
-/* Opcode $49: EOR #imm */
-{
- AC_OP_IMM (^);
-}
-
-
-
-static void OPC_6502_4A (CPUInstance* D)
-/* Opcode $4A: LSR a */
-{
- D->Cycles = 2;
- SET_CF (D->Regs.AC & 0x01);
- D->Regs.AC >>= 1;
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_4C (CPUInstance* D)
-/* Opcode $4C: JMP abs */
-{
- D->Cycles = 3;
- D->Regs.PC = MemReadWord (D->Regs.PC+1);
-}
-
-
-
-static void OPC_6502_4D (CPUInstance* D)
-/* Opcode $4D: EOR abs */
-{
- AC_OP_ABS (^);
-}
-
-
-
-static void OPC_6502_4E (CPUInstance* D)
-/* Opcode $4E: LSR abs */
-{
- unsigned Addr;
- unsigned char Val;
- D->Cycles = 6;
- Addr = MemReadWord (D->Regs.PC+1);
- Val = MemReadByte (Addr);
- SET_CF (Val & 0x01);
- Val >>= 1;
- MemWriteByte (Addr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_50 (CPUInstance* D)
-/* Opcode $50: BVC */
-{
- BRANCH (!GET_OF ());
-}
-
-
-
-static void OPC_6502_51 (CPUInstance* D)
-/* Opcode $51: EOR (zp),y */
-{
- AC_OP_ZPINDY (^);
-}
-
-
-
-static void OPC_6502_55 (CPUInstance* D)
-/* Opcode $55: EOR zp,x */
-{
- AC_OP_ZPX (^);
-}
-
-
-
-static void OPC_6502_56 (CPUInstance* D)
-/* Opcode $56: LSR zp,x */
-{
- unsigned char ZPAddr;
- unsigned char Val;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (ZPAddr);
- SET_CF (Val & 0x01);
- Val >>= 1;
- MemWriteByte (ZPAddr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_58 (CPUInstance* D)
-/* Opcode $58: CLI */
-{
- D->Cycles = 2;
- SET_IF (0);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_59 (CPUInstance* D)
-/* Opcode $59: EOR abs,y */
-{
- AC_OP_ABSY (^);
-}
-
-
-
-static void OPC_6502_5D (CPUInstance* D)
-/* Opcode $5D: EOR abs,x */
-{
- AC_OP_ABSX (^);
-}
-
-
-
-static void OPC_6502_5E (CPUInstance* D)
-/* Opcode $5E: LSR abs,x */
-{
- unsigned Addr;
- unsigned char Val;
- D->Cycles = 7;
- Addr = MemReadWord (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (Addr);
- SET_CF (Val & 0x01);
- Val >>= 1;
- MemWriteByte (Addr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_60 (CPUInstance* D)
-/* Opcode $60: RTS */
-{
- D->Cycles = 6;
- D->Regs.PC = POP (); /* PCL */
- D->Regs.PC |= (POP () << 8); /* PCH */
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_61 (CPUInstance* D)
-/* Opcode $61: ADC (zp,x) */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Addr = MemReadZPWord (ZPAddr);
- ADC (MemReadByte (Addr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_65 (CPUInstance* D)
-/* Opcode $65: ADC zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- ADC (MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_66 (CPUInstance* D)
-/* Opcode $66: ROR zp */
-{
- unsigned char ZPAddr;
- unsigned Val;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (ZPAddr);
- ROR (Val);
- MemWriteByte (ZPAddr, Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_68 (CPUInstance* D)
-/* Opcode $68: PLA */
-{
- D->Cycles = 4;
- D->Regs.AC = POP ();
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_69 (CPUInstance* D)
-/* Opcode $69: ADC #imm */
-{
- D->Cycles = 2;
- ADC (MemReadByte (D->Regs.PC+1));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_6A (CPUInstance* D)
-/* Opcode $6A: ROR a */
-{
- D->Cycles = 2;
- ROR (D->Regs.AC);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_6C (CPUInstance* D)
-/* Opcode $6C: JMP (ind) */
-{
- unsigned PC, Lo, Hi;
- D->Cycles = 5;
- PC = D->Regs.PC;
- Lo = MemReadWord (PC+1);
-
- /* Emulate the 6502 bug */
- D->Regs.PC = MemReadByte (Lo);
- Hi = (Lo & 0xFF00) | ((Lo + 1) & 0xFF);
- D->Regs.PC |= (MemReadByte (Hi) << 8);
-
- /* Output a warning if the bug is triggered */
- if (Hi != Lo + 1) {
- Sim->Warning ("6502 indirect jump bug triggered at $%04X, ind addr = $%04X",
- PC, Lo);
- }
-}
-
-
-
-static void OPC_65C02_6C (CPUInstance* D)
-/* Opcode $6C: JMP (ind) */
-{
- /* 6502 bug fixed here */
- D->Cycles = 5;
- D->Regs.PC = MemReadWord (MemReadWord (D->Regs.PC+1));
-}
-
-
-
-static void OPC_6502_6D (CPUInstance* D)
-/* Opcode $6D: ADC abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- ADC (MemReadByte (Addr));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_6E (CPUInstance* D)
-/* Opcode $6E: ROR abs */
-{
- unsigned Addr;
- unsigned Val;
- D->Cycles = 6;
- Addr = MemReadWord (D->Regs.PC+1);
- Val = MemReadByte (Addr);
- ROR (Val);
- MemWriteByte (Addr, Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_70 (CPUInstance* D)
-/* Opcode $70: BVS */
-{
- BRANCH (GET_OF ());
-}
-
-
-
-static void OPC_6502_71 (CPUInstance* D)
-/* Opcode $71: ADC (zp),y */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Addr = MemReadZPWord (ZPAddr);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- ADC (MemReadByte (Addr + D->Regs.YR));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_75 (CPUInstance* D)
-/* Opcode $75: ADC zp,x */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- ADC (MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_76 (CPUInstance* D)
-/* Opcode $76: ROR zp,x */
-{
- unsigned char ZPAddr;
- unsigned Val;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (ZPAddr);
- ROR (Val);
- MemWriteByte (ZPAddr, Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_78 (CPUInstance* D)
-/* Opcode $78: SEI */
-{
- D->Cycles = 2;
- SET_IF (1);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_79 (CPUInstance* D)
-/* Opcode $79: ADC abs,y */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- ADC (MemReadByte (Addr + D->Regs.YR));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_7D (CPUInstance* D)
-/* Opcode $7D: ADC abs,x */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.XR)) {
- ++D->Cycles;
- }
- ADC (MemReadByte (Addr + D->Regs.XR));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_7E (CPUInstance* D)
-/* Opcode $7E: ROR abs,x */
-{
- unsigned Addr;
- unsigned Val;
- D->Cycles = 7;
- Addr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (Addr);
- ROR (Val);
- MemWriteByte (Addr, Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_81 (CPUInstance* D)
-/* Opcode $81: STA (zp,x) */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Addr = MemReadZPWord (ZPAddr);
- MemWriteByte (Addr, D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_84 (CPUInstance* D)
-/* Opcode $84: STY zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- MemWriteByte (ZPAddr, D->Regs.YR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_85 (CPUInstance* D)
-/* Opcode $85: STA zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- MemWriteByte (ZPAddr, D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_86 (CPUInstance* D)
-/* Opcode $86: STX zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- MemWriteByte (ZPAddr, D->Regs.XR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_88 (CPUInstance* D)
-/* Opcode $88: DEY */
-{
- D->Cycles = 2;
- D->Regs.YR = (D->Regs.YR - 1) & 0xFF;
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_8A (CPUInstance* D)
-/* Opcode $8A: TXA */
-{
- D->Cycles = 2;
- D->Regs.AC = D->Regs.XR;
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_8C (CPUInstance* D)
-/* Opcode $8C: STY abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- MemWriteByte (Addr, D->Regs.YR);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_8D (CPUInstance* D)
-/* Opcode $8D: STA abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- MemWriteByte (Addr, D->Regs.AC);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_8E (CPUInstance* D)
-/* Opcode $8E: STX abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- MemWriteByte (Addr, D->Regs.XR);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_90 (CPUInstance* D)
-/* Opcode $90: BCC */
-{
- BRANCH (!GET_CF ());
-}
-
-
-
-static void OPC_6502_91 (CPUInstance* D)
-/* Opcode $91: sta (zp),y */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Addr = MemReadZPWord (ZPAddr) + D->Regs.YR;
- MemWriteByte (Addr, D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_94 (CPUInstance* D)
-/* Opcode $94: STY zp,x */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- MemWriteByte (ZPAddr, D->Regs.YR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_95 (CPUInstance* D)
-/* Opcode $95: STA zp,x */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- MemWriteByte (ZPAddr, D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_96 (CPUInstance* D)
-/* Opcode $96: stx zp,y */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.YR;
- MemWriteByte (ZPAddr, D->Regs.XR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_98 (CPUInstance* D)
-/* Opcode $98: TYA */
-{
- D->Cycles = 2;
- D->Regs.AC = D->Regs.YR;
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_99 (CPUInstance* D)
-/* Opcode $99: STA abs,y */
-{
- unsigned Addr;
- D->Cycles = 5;
- Addr = MemReadWord (D->Regs.PC+1) + D->Regs.YR;
- MemWriteByte (Addr, D->Regs.AC);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_9A (CPUInstance* D)
-/* Opcode $9A: TXS */
-{
- D->Cycles = 2;
- D->Regs.SP = D->Regs.XR;
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_9D (CPUInstance* D)
-/* Opcode $9D: STA abs,x */
-{
- unsigned Addr;
- D->Cycles = 5;
- Addr = MemReadWord (D->Regs.PC+1) + D->Regs.XR;
- MemWriteByte (Addr, D->Regs.AC);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_A0 (CPUInstance* D)
-/* Opcode $A0: LDY #imm */
-{
- D->Cycles = 2;
- D->Regs.YR = MemReadByte (D->Regs.PC+1);
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A1 (CPUInstance* D)
-/* Opcode $A1: LDA (zp,x) */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Addr = MemReadZPWord (ZPAddr);
- D->Regs.AC = MemReadByte (Addr);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A2 (CPUInstance* D)
-/* Opcode $A2: LDX #imm */
-{
- D->Cycles = 2;
- D->Regs.XR = MemReadByte (D->Regs.PC+1);
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A4 (CPUInstance* D)
-/* Opcode $A4: LDY zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- D->Regs.YR = MemReadByte (ZPAddr);
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A5 (CPUInstance* D)
-/* Opcode $A5: LDA zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- D->Regs.AC = MemReadByte (ZPAddr);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A6 (CPUInstance* D)
-/* Opcode $A6: LDX zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- D->Regs.XR = MemReadByte (ZPAddr);
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A8 (CPUInstance* D)
-/* Opcode $A8: TAY */
-{
- D->Cycles = 2;
- D->Regs.YR = D->Regs.AC;
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_A9 (CPUInstance* D)
-/* Opcode $A9: LDA #imm */
-{
- D->Cycles = 2;
- D->Regs.AC = MemReadByte (D->Regs.PC+1);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_AA (CPUInstance* D)
-/* Opcode $AA: TAX */
-{
- D->Cycles = 2;
- D->Regs.XR = D->Regs.AC;
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_AC (CPUInstance* D)
-/* Opcode $D->Regs.AC: LDY abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- D->Regs.YR = MemReadByte (Addr);
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_AD (CPUInstance* D)
-/* Opcode $AD: LDA abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- D->Regs.AC = MemReadByte (Addr);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_AE (CPUInstance* D)
-/* Opcode $AE: LDX abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- D->Regs.XR = MemReadByte (Addr);
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_B0 (CPUInstance* D)
-/* Opcode $B0: BCS */
-{
- BRANCH (GET_CF ());
-}
-
-
-
-static void OPC_6502_B1 (CPUInstance* D)
-/* Opcode $B1: LDA (zp),y */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Addr = MemReadZPWord (ZPAddr);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- D->Regs.AC = MemReadByte (Addr + D->Regs.YR);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B4 (CPUInstance* D)
-/* Opcode $B4: LDY zp,x */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- D->Regs.YR = MemReadByte (ZPAddr);
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B5 (CPUInstance* D)
-/* Opcode $B5: LDA zp,x */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- D->Regs.AC = MemReadByte (ZPAddr);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B6 (CPUInstance* D)
-/* Opcode $B6: LDX zp,y */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.YR;
- D->Regs.XR = MemReadByte (ZPAddr);
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B8 (CPUInstance* D)
-/* Opcode $B8: CLV */
-{
- D->Cycles = 2;
- SET_OF (0);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_B9 (CPUInstance* D)
-/* Opcode $B9: LDA abs,y */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- D->Regs.AC = MemReadByte (Addr + D->Regs.YR);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_BA (CPUInstance* D)
-/* Opcode $BA: TSX */
-{
- D->Cycles = 2;
- D->Regs.XR = D->Regs.SP;
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_BC (CPUInstance* D)
-/* Opcode $BC: LDY abs,x */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.XR)) {
- ++D->Cycles;
- }
- D->Regs.YR = MemReadByte (Addr + D->Regs.XR);
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_BD (CPUInstance* D)
-/* Opcode $BD: LDA abs,x */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.XR)) {
- ++D->Cycles;
- }
- D->Regs.AC = MemReadByte (Addr + D->Regs.XR);
- TEST_ZF (D->Regs.AC);
- TEST_SF (D->Regs.AC);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_BE (CPUInstance* D)
-/* Opcode $BE: LDX abs,y */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- D->Regs.XR = MemReadByte (Addr + D->Regs.YR);
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_C0 (CPUInstance* D)
-/* Opcode $C0: CPY #imm */
-{
- D->Cycles = 2;
- CMP (D->Regs.YR, MemReadByte (D->Regs.PC+1));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C1 (CPUInstance* D)
-/* Opcode $C1: CMP (zp,x) */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Addr = MemReadZPWord (ZPAddr);
- CMP (D->Regs.AC, MemReadByte (Addr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C4 (CPUInstance* D)
-/* Opcode $C4: CPY zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- CMP (D->Regs.YR, MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C5 (CPUInstance* D)
-/* Opcode $C5: CMP zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- CMP (D->Regs.AC, MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C6 (CPUInstance* D)
-/* Opcode $C6: DEC zp */
-{
- unsigned char ZPAddr;
- unsigned char Val;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (ZPAddr) - 1;
- MemWriteByte (ZPAddr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C8 (CPUInstance* D)
-/* Opcode $C8: INY */
-{
- D->Cycles = 2;
- D->Regs.YR = (D->Regs.YR + 1) & 0xFF;
- TEST_ZF (D->Regs.YR);
- TEST_SF (D->Regs.YR);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_C9 (CPUInstance* D)
-/* Opcode $C9: CMP #imm */
-{
- D->Cycles = 2;
- CMP (D->Regs.AC, MemReadByte (D->Regs.PC+1));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_CA (CPUInstance* D)
-/* Opcode $CA: DEX */
-{
- D->Cycles = 2;
- D->Regs.XR = (D->Regs.XR - 1) & 0xFF;
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_CC (CPUInstance* D)
-/* Opcode $CC: CPY abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- CMP (D->Regs.YR, MemReadByte (Addr));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_CD (CPUInstance* D)
-/* Opcode $CD: CMP abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- CMP (D->Regs.AC, MemReadByte (Addr));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_CE (CPUInstance* D)
-/* Opcode $CE: DEC abs */
-{
- unsigned Addr;
- unsigned char Val;
- D->Cycles = 6;
- Addr = MemReadWord (D->Regs.PC+1);
- Val = MemReadByte (Addr) - 1;
- MemWriteByte (Addr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_D0 (CPUInstance* D)
-/* Opcode $D0: BNE */
-{
- BRANCH (!GET_ZF ());
-}
-
-
-
-static void OPC_6502_D1 (CPUInstance* D)
-/* Opcode $D1: CMP (zp),y */
-{
- unsigned ZPAddr;
- unsigned Addr;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Addr = MemReadWord (ZPAddr);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- CMP (D->Regs.AC, MemReadByte (Addr + D->Regs.YR));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_D5 (CPUInstance* D)
-/* Opcode $D5: CMP zp,x */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- CMP (D->Regs.AC, MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_D6 (CPUInstance* D)
-/* Opcode $D6: DEC zp,x */
-{
- unsigned char ZPAddr;
- unsigned char Val;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (ZPAddr) - 1;
- MemWriteByte (ZPAddr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_D8 (CPUInstance* D)
-/* Opcode $D8: CLD */
-{
- D->Cycles = 2;
- SET_DF (0);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_D9 (CPUInstance* D)
-/* Opcode $D9: CMP abs,y */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- CMP (D->Regs.AC, MemReadByte (Addr + D->Regs.YR));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_DD (CPUInstance* D)
-/* Opcode $DD: CMP abs,x */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.XR)) {
- ++D->Cycles;
- }
- CMP (D->Regs.AC, MemReadByte (Addr + D->Regs.XR));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_DE (CPUInstance* D)
-/* Opcode $DE: DEC abs,x */
-{
- unsigned Addr;
- unsigned char Val;
- D->Cycles = 7;
- Addr = MemReadWord (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (Addr) - 1;
- MemWriteByte (Addr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_E0 (CPUInstance* D)
-/* Opcode $E0: CPX #imm */
-{
- D->Cycles = 2;
- CMP (D->Regs.XR, MemReadByte (D->Regs.PC+1));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E1 (CPUInstance* D)
-/* Opcode $E1: SBC (zp,x) */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Addr = MemReadZPWord (ZPAddr);
- SBC (MemReadByte (Addr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E4 (CPUInstance* D)
-/* Opcode $E4: CPX zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- CMP (D->Regs.XR, MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E5 (CPUInstance* D)
-/* Opcode $E5: SBC zp */
-{
- unsigned char ZPAddr;
- D->Cycles = 3;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- SBC (MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E6 (CPUInstance* D)
-/* Opcode $E6: INC zp */
-{
- unsigned char ZPAddr;
- unsigned char Val;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Val = MemReadByte (ZPAddr) + 1;
- MemWriteByte (ZPAddr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E8 (CPUInstance* D)
-/* Opcode $E8: INX */
-{
- D->Cycles = 2;
- D->Regs.XR = (D->Regs.XR + 1) & 0xFF;
- TEST_ZF (D->Regs.XR);
- TEST_SF (D->Regs.XR);
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_E9 (CPUInstance* D)
-/* Opcode $E9: SBC #imm */
-{
- D->Cycles = 2;
- SBC (MemReadByte (D->Regs.PC+1));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_EA (CPUInstance* D)
-/* Opcode $EA: NOP */
-{
- /* This one is easy... */
- D->Cycles = 2;
- D->Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_EC (CPUInstance* D)
-/* Opcode $EC: CPX abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- CMP (D->Regs.XR, MemReadByte (Addr));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_ED (CPUInstance* D)
-/* Opcode $ED: SBC abs */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- SBC (MemReadByte (Addr));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_EE (CPUInstance* D)
-/* Opcode $EE: INC abs */
-{
- unsigned Addr;
- unsigned char Val;
- D->Cycles = 6;
- Addr = MemReadWord (D->Regs.PC+1);
- Val = MemReadByte (Addr) + 1;
- MemWriteByte (Addr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_F0 (CPUInstance* D)
-/* Opcode $F0: BEQ */
-{
- BRANCH (GET_ZF ());
-}
-
-
-
-static void OPC_6502_F1 (CPUInstance* D)
-/* Opcode $F1: SBC (zp),y */
-{
- unsigned char ZPAddr;
- unsigned Addr;
- D->Cycles = 5;
- ZPAddr = MemReadByte (D->Regs.PC+1);
- Addr = MemReadZPWord (ZPAddr);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- SBC (MemReadByte (Addr + D->Regs.YR));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_F5 (CPUInstance* D)
-/* Opcode $F5: SBC zp,x */
-{
- unsigned char ZPAddr;
- D->Cycles = 4;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- SBC (MemReadByte (ZPAddr));
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_F6 (CPUInstance* D)
-/* Opcode $F6: INC zp,x */
-{
- unsigned char ZPAddr;
- unsigned char Val;
- D->Cycles = 6;
- ZPAddr = MemReadByte (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (ZPAddr) + 1;
- MemWriteByte (ZPAddr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_F8 (CPUInstance* D)
-/* Opcode $F8: SED */
-{
- SET_DF (1);
-}
-
-
-
-static void OPC_6502_F9 (CPUInstance* D)
-/* Opcode $F9: SBC abs,y */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.YR)) {
- ++D->Cycles;
- }
- SBC (MemReadByte (Addr + D->Regs.YR));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_FD (CPUInstance* D)
-/* Opcode $FD: SBC abs,x */
-{
- unsigned Addr;
- D->Cycles = 4;
- Addr = MemReadWord (D->Regs.PC+1);
- if (PAGE_CROSS (Addr, D->Regs.XR)) {
- ++D->Cycles;
- }
- SBC (MemReadByte (Addr + D->Regs.XR));
- D->Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_FE (CPUInstance* D)
-/* Opcode $FE: INC abs,x */
-{
- unsigned Addr;
- unsigned char Val;
- D->Cycles = 7;
- Addr = MemReadWord (D->Regs.PC+1) + D->Regs.XR;
- Val = MemReadByte (Addr) + 1;
- MemWriteByte (Addr, Val);
- TEST_ZF (Val);
- TEST_SF (Val);
- D->Regs.PC += 3;
-}
-
-
-
-/*****************************************************************************/
-/* Opcode handler tables */
-/*****************************************************************************/
-
-
-
-/* Opcode handler table for the 6502 */
-static const OPFunc OP6502Table[256] = {
- OPC_6502_00,
- OPC_6502_01,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_05,
- OPC_6502_06,
- OPC_Illegal,
- OPC_6502_08,
- OPC_6502_09,
- OPC_6502_0A,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_0D,
- OPC_6502_0E,
- OPC_Illegal,
- OPC_6502_10,
- OPC_6502_11,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_15,
- OPC_6502_16,
- OPC_Illegal,
- OPC_6502_18,
- OPC_6502_19,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_1D,
- OPC_6502_1E,
- OPC_Illegal,
- OPC_6502_20,
- OPC_6502_21,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_24,
- OPC_6502_25,
- OPC_6502_26,
- OPC_Illegal,
- OPC_6502_28,
- OPC_6502_29,
- OPC_6502_2A,
- OPC_Illegal,
- OPC_6502_2C,
- OPC_6502_2D,
- OPC_6502_2E,
- OPC_Illegal,
- OPC_6502_30,
- OPC_6502_31,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_35,
- OPC_6502_36,
- OPC_Illegal,
- OPC_6502_38,
- OPC_6502_39,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_3D,
- OPC_6502_3E,
- OPC_Illegal,
- OPC_6502_40,
- OPC_6502_41,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_45,
- OPC_6502_46,
- OPC_Illegal,
- OPC_6502_48,
- OPC_6502_49,
- OPC_6502_4A,
- OPC_Illegal,
- OPC_6502_4C,
- OPC_6502_4D,
- OPC_6502_4E,
- OPC_Illegal,
- OPC_6502_50,
- OPC_6502_51,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_55,
- OPC_6502_56,
- OPC_Illegal,
- OPC_6502_58,
- OPC_6502_59,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_5D,
- OPC_6502_5E,
- OPC_Illegal,
- OPC_6502_60,
- OPC_6502_61,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_65,
- OPC_6502_66,
- OPC_Illegal,
- OPC_6502_68,
- OPC_6502_69,
- OPC_6502_6A,
- OPC_Illegal,
- OPC_6502_6C,
- OPC_6502_6D,
- OPC_6502_6E,
- OPC_Illegal,
- OPC_6502_70,
- OPC_6502_71,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_75,
- OPC_6502_76,
- OPC_Illegal,
- OPC_6502_78,
- OPC_6502_79,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_7D,
- OPC_6502_7E,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_81,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_84,
- OPC_6502_85,
- OPC_6502_86,
- OPC_Illegal,
- OPC_6502_88,
- OPC_Illegal,
- OPC_6502_8A,
- OPC_Illegal,
- OPC_6502_8C,
- OPC_6502_8D,
- OPC_6502_8E,
- OPC_Illegal,
- OPC_6502_90,
- OPC_6502_91,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_94,
- OPC_6502_95,
- OPC_6502_96,
- OPC_Illegal,
- OPC_6502_98,
- OPC_6502_99,
- OPC_6502_9A,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_9D,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_A0,
- OPC_6502_A1,
- OPC_6502_A2,
- OPC_Illegal,
- OPC_6502_A4,
- OPC_6502_A5,
- OPC_6502_A6,
- OPC_Illegal,
- OPC_6502_A8,
- OPC_6502_A9,
- OPC_6502_AA,
- OPC_Illegal,
- OPC_6502_AC,
- OPC_6502_AD,
- OPC_6502_AE,
- OPC_Illegal,
- OPC_6502_B0,
- OPC_6502_B1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_B4,
- OPC_6502_B5,
- OPC_6502_B6,
- OPC_Illegal,
- OPC_6502_B8,
- OPC_6502_B9,
- OPC_6502_BA,
- OPC_Illegal,
- OPC_6502_BC,
- OPC_6502_BD,
- OPC_6502_BE,
- OPC_Illegal,
- OPC_6502_C0,
- OPC_6502_C1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_C4,
- OPC_6502_C5,
- OPC_6502_C6,
- OPC_Illegal,
- OPC_6502_C8,
- OPC_6502_C9,
- OPC_6502_CA,
- OPC_Illegal,
- OPC_6502_CC,
- OPC_6502_CD,
- OPC_6502_CE,
- OPC_Illegal,
- OPC_6502_D0,
- OPC_6502_D1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_D5,
- OPC_6502_D6,
- OPC_Illegal,
- OPC_6502_D8,
- OPC_6502_D9,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_DD,
- OPC_6502_DE,
- OPC_Illegal,
- OPC_6502_E0,
- OPC_6502_E1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_E4,
- OPC_6502_E5,
- OPC_6502_E6,
- OPC_Illegal,
- OPC_6502_E8,
- OPC_6502_E9,
- OPC_6502_EA,
- OPC_Illegal,
- OPC_6502_EC,
- OPC_6502_ED,
- OPC_6502_EE,
- OPC_Illegal,
- OPC_6502_F0,
- OPC_6502_F1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_F5,
- OPC_6502_F6,
- OPC_Illegal,
- OPC_6502_F8,
- OPC_6502_F9,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_FD,
- OPC_6502_FE,
- OPC_Illegal,
-};
-
-
-
-/* Opcode handler table for the 65C02 */
-static const OPFunc OP65C02Table[256] = {
- OPC_6502_00,
- OPC_6502_01,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_05,
- OPC_6502_06,
- OPC_Illegal,
- OPC_6502_08,
- OPC_6502_09,
- OPC_6502_0A,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_0D,
- OPC_6502_0E,
- OPC_Illegal,
- OPC_6502_10,
- OPC_6502_11,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_15,
- OPC_6502_16,
- OPC_Illegal,
- OPC_6502_18,
- OPC_6502_19,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_1D,
- OPC_6502_1E,
- OPC_Illegal,
- OPC_6502_20,
- OPC_6502_21,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_24,
- OPC_6502_25,
- OPC_6502_26,
- OPC_Illegal,
- OPC_6502_28,
- OPC_6502_29,
- OPC_6502_2A,
- OPC_Illegal,
- OPC_6502_2C,
- OPC_6502_2D,
- OPC_6502_2E,
- OPC_Illegal,
- OPC_6502_30,
- OPC_6502_31,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_35,
- OPC_6502_36,
- OPC_Illegal,
- OPC_6502_38,
- OPC_6502_39,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_3D,
- OPC_6502_3E,
- OPC_Illegal,
- OPC_6502_40,
- OPC_6502_41,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_45,
- OPC_6502_46,
- OPC_Illegal,
- OPC_6502_48,
- OPC_6502_49,
- OPC_6502_4A,
- OPC_Illegal,
- OPC_6502_4C,
- OPC_6502_4D,
- OPC_6502_4E,
- OPC_Illegal,
- OPC_6502_50,
- OPC_6502_51,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_55,
- OPC_6502_56,
- OPC_Illegal,
- OPC_6502_58,
- OPC_6502_59,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_5D,
- OPC_6502_5E,
- OPC_Illegal,
- OPC_6502_60,
- OPC_6502_61,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_65,
- OPC_6502_66,
- OPC_Illegal,
- OPC_6502_68,
- OPC_6502_69,
- OPC_6502_6A,
- OPC_Illegal,
- OPC_65C02_6C,
- OPC_6502_6D,
- OPC_6502_6E,
- OPC_Illegal,
- OPC_6502_70,
- OPC_6502_71,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_75,
- OPC_6502_76,
- OPC_Illegal,
- OPC_6502_78,
- OPC_6502_79,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_7D,
- OPC_6502_7E,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_81,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_84,
- OPC_6502_85,
- OPC_6502_86,
- OPC_Illegal,
- OPC_6502_88,
- OPC_Illegal,
- OPC_6502_8A,
- OPC_Illegal,
- OPC_6502_8C,
- OPC_6502_8D,
- OPC_6502_8E,
- OPC_Illegal,
- OPC_6502_90,
- OPC_6502_91,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_94,
- OPC_6502_95,
- OPC_6502_96,
- OPC_Illegal,
- OPC_6502_98,
- OPC_6502_99,
- OPC_6502_9A,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_9D,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_A0,
- OPC_6502_A1,
- OPC_6502_A2,
- OPC_Illegal,
- OPC_6502_A4,
- OPC_6502_A5,
- OPC_6502_A6,
- OPC_Illegal,
- OPC_6502_A8,
- OPC_6502_A9,
- OPC_6502_AA,
- OPC_Illegal,
- OPC_6502_AC,
- OPC_6502_AD,
- OPC_6502_AE,
- OPC_Illegal,
- OPC_6502_B0,
- OPC_6502_B1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_B4,
- OPC_6502_B5,
- OPC_6502_B6,
- OPC_Illegal,
- OPC_6502_B8,
- OPC_6502_B9,
- OPC_6502_BA,
- OPC_Illegal,
- OPC_6502_BC,
- OPC_6502_BD,
- OPC_6502_BE,
- OPC_Illegal,
- OPC_6502_C0,
- OPC_6502_C1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_C4,
- OPC_6502_C5,
- OPC_6502_C6,
- OPC_Illegal,
- OPC_6502_C8,
- OPC_6502_C9,
- OPC_6502_CA,
- OPC_Illegal,
- OPC_6502_CC,
- OPC_6502_CD,
- OPC_6502_CE,
- OPC_Illegal,
- OPC_6502_D0,
- OPC_6502_D1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_D5,
- OPC_6502_D6,
- OPC_Illegal,
- OPC_6502_D8,
- OPC_6502_D9,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_DD,
- OPC_6502_DE,
- OPC_Illegal,
- OPC_6502_E0,
- OPC_6502_E1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_E4,
- OPC_6502_E5,
- OPC_6502_E6,
- OPC_Illegal,
- OPC_6502_E8,
- OPC_6502_E9,
- OPC_6502_EA,
- OPC_Illegal,
- OPC_6502_EC,
- OPC_6502_ED,
- OPC_6502_EE,
- OPC_Illegal,
- OPC_6502_F0,
- OPC_6502_F1,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_F5,
- OPC_6502_F6,
- OPC_Illegal,
- OPC_6502_F8,
- OPC_6502_F9,
- OPC_Illegal,
- OPC_Illegal,
- OPC_Illegal,
- OPC_6502_FD,
- OPC_6502_FE,
- OPC_Illegal,
-};
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-static void Init (const SimData* S)
-/* Initialize the module */
-{
- /* Remember the data pointer */
- Sim = S;
-}
-
-
-
-static void* Create6502Instance (void* CfgInfo)
-/* Create an instance of a 6502 CPU */
-{
- return NewCPUInstance (OP6502Table, CfgInfo);
-}
-
-
-
-static void* Create65C02Instance (void* CfgInfo)
-/* Create an instance of a 65C02 CPU */
-{
- return NewCPUInstance (OP65C02Table, CfgInfo);
-}
-
-
-
-static void DestroyInstance (void* Instance)
-/* Destroy an instance of a CPU */
-{
- /* Free the instance */
- DeleteCPUInstance (Instance);
-}
-
-
-
-static void IRQRequest (void* Data)
-/* Generate an IRQ */
-{
- /* Cast the pointer */
- CPUInstance* D = (CPUInstance*) Data;
-
- /* Remember the request */
- D->HaveIRQRequest = 1;
-}
-
-
-
-static void NMIRequest (void* Data)
-/* Generate an NMI */
-{
- /* Cast the pointer */
- CPUInstance* D = (CPUInstance*) Data;
-
- /* Remember the request */
- D->HaveNMIRequest = 1;
-}
-
-
-
-static void Reset (void* Data)
-/* Generate a CPU RESET */
-{
- /* Cast the pointer */
- CPUInstance* D = (CPUInstance*) Data;
-
- /* Reset the CPU */
- D->HaveIRQRequest = 0;
- D->HaveNMIRequest = 0;
- D->CPUHalted = 0;
- D->Regs.SR = 0;
- D->Regs.PC = MemReadWord (0xFFFC);
-}
-
-
-
-static unsigned ExecuteInsn (void* Data)
-/* Execute one CPU instruction */
-{
- /* Cast the pointer */
- CPUInstance* D = (CPUInstance*) Data;
-
- /* If the CPU is halted, do nothing */
- if (D->CPUHalted) {
- return 0;
- }
-
- /* If we have an NMI request, handle it */
- if (D->HaveNMIRequest) {
-
- D->HaveNMIRequest = 0;
- PUSH (PCH);
- PUSH (PCL);
- PUSH (D->Regs.SR);
- SET_IF (1);
- D->Regs.PC = MemReadWord (0xFFFA);
- D->Cycles = 7;
-
- } else if (D->HaveIRQRequest && GET_IF () == 0) {
-
- D->HaveIRQRequest = 0;
- PUSH (PCH);
- PUSH (PCL);
- PUSH (D->Regs.SR);
- SET_IF (1);
- D->Regs.PC = MemReadWord (0xFFFE);
- D->Cycles = 7;
-
- } else {
-
- /* Normal instruction - read the next opcode */
- unsigned char OPC = MemReadByte (D->Regs.PC);
-
- /* Execute it */
- D->Handlers[OPC] (D);
-
- }
-
- /* Count cycles */
- D->TotalCycles += D->Cycles;
-
- /* Return the number of clock cycles needed by this insn */
- return D->Cycles;
-}
-
-
-
-static unsigned long GetCycles (void* Data)
-/* Return the total number of cycles executed */
-{
- /* Cast the pointer */
- CPUInstance* D = (CPUInstance*) Data;
-
- /* Return the total number of cycles */
- return D->TotalCycles;
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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 */
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
- }
-}
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
-#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;
{
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",
-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 */
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 },
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) {
LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
break;
- case 'd':
- OptDebug (Arg, 0);
- break;
-
case 'h':
case '?':
OptHelp (Arg, 0);
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;
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;
}
}
++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;
}
-
-
-
-#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"
-/* Pointer to our memory */
-static const ChipInstance** MemData = 0;
-unsigned MemSize = 0;
+/* THE memory */
+static unsigned char Mem[0x10000];
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;
}
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];
}
-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;
-
- /* 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;
- }
-}
-
-
+ /* Fill momory with illegal opcode */
+ memset (Mem, 0xFF, sizeof (Mem));
+ /* Set RESET vector to 0x0200 */
+ Mem[0xFFFC] = 0x00;
+ Mem[0xFFFD] = 0x02;
+}
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-/* Forwards */
-struct ChipInstance;
-
-/* Memory size of the CPU */
-extern unsigned MemSize;
-
-
-
/*****************************************************************************/
/* Code */
/*****************************************************************************/
* 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 */
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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;
+}
--- /dev/null
+/*****************************************************************************/
+/* */
+/* paravirt.h */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef PARAVIRT_H
+#define PARAVIRT_H
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void ParaVirtualization (CPURegs* Regs);
+/* Potentially execute paravirtualization hook */
+
+
+
+/* End of paravirt.h */
+
+#endif
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
- }
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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;
-}
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-