Steve2/src/cpu/6502.h

285 lines
7.8 KiB
C

//
// 6502.h
// 6502
//
// Created by Tamas Rudnai on 7/22/19.
// Copyright © 2019, 2020 Tamas Rudnai. All rights reserved.
//
// This file is part of Steve ][ -- The Apple ][ Emulator.
//
// Steve ][ is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Steve ][ is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Steve ][. If not, see <https://www.gnu.org/licenses/>.
//
#ifndef __6502_H__
#define __6502_H__
#include <stdint.h>
#include "common.h"
#include "woz.h"
//#ifdef DISASSEMBLER
//#define INSTR INLINE static
//#else
//#define INSTR INLINE static
//#endif
#ifdef DEBUG
#define INSTR static
#else
#define INSTR static inline __attribute__((always_inline)) UNUSED
//#define INSTR static inline __attribute__((always_inline)) __attribute__((regcall)) UNUSED
#endif
#define CRYSTAL_MHZ 14.31818 // NTSC version (original)
#define DEFAULT_MHZ_6502 (CRYSTAL_MHZ / 14) // 1.023 MHz
typedef enum cpuMode_e {
cpuMode_normal = 0,
cpuMode_eco,
cpuMode_game,
} cpuMode_s;
typedef enum cpuState_e {
cpuState_unknown = 0,
cpuState_inited,
cpuState_running,
cpuState_executing,
cpuState_halting,
cpuState_halted,
} cpuState_s;
extern volatile cpuMode_s cpuMode;
extern volatile cpuState_s cpuState;
extern const double default_MHz_6502;
extern const double iigs_MHz_6502;
extern const double iicplus_MHz_6502;
extern double MHz_6502;
extern unsigned int clk_6502_per_frm;
extern unsigned int clk_6502_per_frm_set;
extern unsigned int clk_6502_per_frm_max;
extern unsigned int clk_6502_per_frm_max_sound;
typedef enum : uint8_t {
NO_INT = 0,
HALT, // HLT instruction
BREAK, // BRK instruction
IRQ,
NMI,
INV, // Invalid Opcode
RET, // RTS/RTI Used by Debugger Step_Over / Step_Out
HARDRESET,
SOFTRESET,
BREAKPOINT,
BREAKIO,
BREAKRDMEM,
BREAKWRMEM,
} interrupt_t;
typedef struct debugMask_s {
uint16_t trace : 1;
uint16_t step : 1;
uint16_t hlt : 1;
uint16_t brk : 1;
uint16_t irq : 1;
uint16_t nmi : 1;
uint16_t inv : 1;
uint16_t out : 1;
uint16_t ret : 1;
uint16_t bra : 1;
uint16_t bra_true : 1;
uint16_t bra_false : 1;
uint16_t compile : 1;
} debugMask_t;
typedef union flags_u {
struct {
uint8_t C:1; // Carry Flag
uint8_t Z:1; // Zero Flag
uint8_t I:1; // Interrupt Flag
uint8_t D:1; // Decimal Flag
uint8_t B:1; // B Flag
uint8_t res:1; // reserved -- should be always 1
uint8_t V:1; // Overflow Flag ???
uint8_t N:1; // Negative Flag
};
uint8_t SR;
} flags_t;
typedef struct debugger_s {
_Bool on; // debugger is on
uint8_t SP; // Stack Pointer for monitoring Return Stack Level -- eg. Step_Out & Step_Over
union {
uint8_t wMask;
debugMask_t mask; // 34: 0: No Debug, 1: Disassembly Only, 2: Run till BRK, 3: StepByStep
};
} debugger_t;
typedef uint32_t clkfrm_t;
//#pragma pack(1)
typedef struct m6502_s {
uint8_t A; // 0: Accumulator
uint8_t X; // 1: X index register
uint8_t Y; // 2: Y index register
// union {
// uint8_t instr; // Instruction
// struct {
// uint8_t cc:2;
// uint8_t bbb:3;
// uint8_t aaa:3;
// };
// };
struct { // no bitfield faster processing
uint8_t C; // 3: Carry Flag
uint8_t Z; // 4: Zero Flag
uint8_t I; // 5: Interrupt Flag
uint8_t D; // 6: Decimal Flag
uint8_t B; // 7: B Flag
uint8_t res; // 8: reserved -- should be always 1
uint8_t V; // 9: Overflow Flag ???
uint8_t N; // 10: Negative Flag
};
uint16_t PC; // 11: Program Counter
uint8_t SP; // 13: Stack Pointer ( stack addr = 0x01 + sp )
// unsigned clk; // Clock Counter
clkfrm_t clktime; // 14:
clkfrm_t clklast; // 15:
clkfrm_t clkfrm; // 16:
// uint64_t clk_wrenable; // CPU clock when WRITE RAM is triggered
clkfrm_t lastIO; // Last time I/O accessed
int ecoSpindown; // spindown counter for eco mode
debugger_t debugger;
union {
unsigned int IF; // interrut flag
interrupt_t interrupt;
};
} m6502_t;
//#pragma pack()
extern const int ecoSpindown; // initial value of ECO Spingdown Counter
// Memory Config
typedef struct MEMcfg_s {
unsigned RAM_16K : 1;
unsigned RAM_128K : 1;
unsigned RD_INT_RAM : 1;
unsigned WR_RAM : 1;
unsigned RAM_BANK_2 : 1;
unsigned AUX_BANK : 1;
unsigned txt_page_2 : 1; // 0: page 1 1: page 2 (aux video memory)
unsigned int_Cx_ROM : 1; // 0: Slot Cx ROM 1: Internal Cx ROM
unsigned slot_C3_ROM : 1; // 0: Internal ROM 1: Slot 3 ROM
unsigned is_80STORE : 1;
unsigned RD_AUX_MEM : 1;
unsigned WR_AUX_MEM : 1;
unsigned ALT_ZP : 1;
unsigned WR_RAM_cntr; // min 2 I/O to enable mem write
} MEMcfg_t;
typedef union videoMode_u {
struct {
uint8_t text : 1; // 0: graphics 1: text
uint8_t col80 : 1; // 0: 40 col 1: 80 col
uint8_t altChr : 1; // 0: normal 1: alternate character set
uint8_t mixed : 1; // 0: no mix 1: mixed graphics and text when in graphics mode
uint8_t hires : 1; // 0: loRes 1: hiRes
};
uint8_t mode;
} videoMode_t;
extern MEMcfg_t MEMcfg;
extern m6502_t m6502;
extern uint8_t * const AUX; // Pointer to the auxiliary memory so we can use this from Swift
extern uint8_t * const RAM;
extern uint8_t * const MEM; // Pointer to the Shadow Memory Map so we can use this from Swift//extern uint8_t * AUX_VID_RAM;
extern uint32_t * videoMemPtr;
extern double * pdl_valarr;
extern double * pdl_prevarr;
extern double * pdl_diffarr;
//extern void hires_Update(void);
extern double mips;
extern double mhz;
#define DEFAULT_FPS 60U
#define DEF_VIDEO_DIV 1U
#define DEF_SPKR_DIV 1U
#define DEF_DRV_LED_DIV 4U
#define ECO_VIDEO_DIV 4U
//#define GAME_FPS 180U // 90U // 120U // 180U // 240U // 480U // 600U
//#define GAME_VIDEO_DIV 1U // (GAME_FPS / DEFAULT_FPS)
//#define GAME_SPKR_DIV 6U // 16U
#define GAME_FPS 180U // 300U // 240U // 180U // 120U
#define GAME_VIDEO_DIV 3U // 4U // (GAME_FPS / DEFAULT_FPS)
#define GAME_SPKR_DIV 3U // 8U // 16U
extern unsigned int video_fps_divider;
extern unsigned int fps;
extern void rom_loadFile( const char * bundlePath, const char * filename );
extern void tst6502(void);
extern void m6502_ColdReset( const char * bundlePath, const char * romFilePath );
INLINE void set_flags_N( const uint8_t test );
INLINE void set_flags_V( const uint8_t test );
INLINE void set_flags_Z( const uint8_t test );
INLINE void set_flags_C( const int16_t test );
INLINE void set_flags_NZ( const uint8_t test );
INLINE void set_flags_NV( const uint8_t test );
INLINE void set_flags_NVZ( const uint8_t test );
INLINE void set_flags_NZC( const int16_t test );
INLINE flags_t getFlags(void);
INLINE void setFlags( uint8_t byte );
extern void m6502_Run(void);
INLINE int m6502_Step(void);
INLINE int m6502_Step_dbg(void);
extern void interrupt_IRQ(void);
extern void interrupt_NMI(void);
extern void hardReset(void);
extern void softReset(void);
extern void openLog(void);
extern void closeLog(void);
#endif /* __6502_H__ */