mirror of
https://github.com/pevans/erc-c.git
synced 2025-07-07 11:24:03 +00:00
Documentation, lacking
This commit is contained in:
@ -9,6 +9,10 @@ extern void log_write(int, const char *, ...);
|
|||||||
extern void log_close();
|
extern void log_close();
|
||||||
extern void log_open(FILE *);
|
extern void log_open(FILE *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we have a couple of convenience macros that abstracts the log
|
||||||
|
* level number.
|
||||||
|
*/
|
||||||
#define log_critical(...) log_write(0, __VA_ARGS__)
|
#define log_critical(...) log_write(0, __VA_ARGS__)
|
||||||
#define log_error(...) log_write(0, __VA_ARGS__)
|
#define log_error(...) log_write(0, __VA_ARGS__)
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#ifndef _MOS6502_ENUMS_H_
|
|
||||||
#define _MOS6502_ENUMS_H_
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mos6502.enums.h
|
* mos6502.enums.h
|
||||||
* Enums and other symbols for use with the mos 6502
|
* Enums and other symbols for use with the mos 6502
|
||||||
@ -11,6 +8,14 @@
|
|||||||
* adding them to the global namespace throughout the application.
|
* adding them to the global namespace throughout the application.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _MOS6502_ENUMS_H_
|
||||||
|
#define _MOS6502_ENUMS_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This defines all of the flags that are possible within the status (P)
|
||||||
|
* register. Note that there is intentionally _no_ definition for the
|
||||||
|
* 6th bit.
|
||||||
|
*/
|
||||||
enum status_flags {
|
enum status_flags {
|
||||||
CARRY = 1,
|
CARRY = 1,
|
||||||
ZERO = 2,
|
ZERO = 2,
|
||||||
@ -21,6 +26,12 @@ enum status_flags {
|
|||||||
NEGATIVE = 128,
|
NEGATIVE = 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we define the various address modes that are possible. These do
|
||||||
|
* not map to any significant numbers that are documented for the 6502
|
||||||
|
* processor; the position of these symbols don't really matter, and are
|
||||||
|
* generally (except for `NOA`, no address mode) in alphabetical order.
|
||||||
|
*/
|
||||||
enum addr_mode {
|
enum addr_mode {
|
||||||
NOA, // no address mode
|
NOA, // no address mode
|
||||||
ACC, // accumulator
|
ACC, // accumulator
|
||||||
@ -38,6 +49,12 @@ enum addr_mode {
|
|||||||
ZPY, // zero page y-index
|
ZPY, // zero page y-index
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These define the various instructions as enum symbols; again, like
|
||||||
|
* for address modes, the values of these enums are not actually
|
||||||
|
* significant to the 6502 processor, and are only useful to we, the
|
||||||
|
* programmers.
|
||||||
|
*/
|
||||||
enum instruction {
|
enum instruction {
|
||||||
ADC, // ADd with Carry
|
ADC, // ADd with Carry
|
||||||
AND, // bitwise AND
|
AND, // bitwise AND
|
||||||
|
@ -29,6 +29,13 @@
|
|||||||
// All of our address modes, instructions, etc. are defined here.
|
// All of our address modes, instructions, etc. are defined here.
|
||||||
#include "mos6502.enums.h"
|
#include "mos6502.enums.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a table which defines what instruction each opcode is mapped
|
||||||
|
* to. All possible (256) values are defined here. You will note many
|
||||||
|
* cases where we use NOP where opcodes are not _technically_ defined;
|
||||||
|
* this may or may not be the best behavior. It's quite possible we should
|
||||||
|
* instead crash the program when we stumble upon such malformed opcodes
|
||||||
|
*/
|
||||||
static int instructions[] = {
|
static int instructions[] = {
|
||||||
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
||||||
BRK, ORA, NOP, NOP, NOP, ORA, ASL, NOP, PHP, ORA, ASL, NOP, NOP, ORA, ASL, NOP, // 0x
|
BRK, ORA, NOP, NOP, NOP, ORA, ASL, NOP, PHP, ORA, ASL, NOP, NOP, ORA, ASL, NOP, // 0x
|
||||||
@ -49,10 +56,17 @@ static int instructions[] = {
|
|||||||
BEQ, SBC, NOP, NOP, NOP, SBC, INC, NOP, SED, SBC, NOP, NOP, NOP, SBC, INC, NOP, // Fx
|
BEQ, SBC, NOP, NOP, NOP, SBC, INC, NOP, SED, SBC, NOP, NOP, NOP, SBC, INC, NOP, // Fx
|
||||||
};
|
};
|
||||||
|
|
||||||
// I just don't want to type out the literal function name every time
|
/*
|
||||||
|
* A small convenience for defining instruction handlers below.
|
||||||
|
*/
|
||||||
#define INST_HANDLER(x) \
|
#define INST_HANDLER(x) \
|
||||||
mos6502_handle_##x
|
mos6502_handle_##x
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here's another table, this time mapping instruction codes to
|
||||||
|
* instruction handler functions. They are listed in the order defined
|
||||||
|
* in the instruction enum (in mos6502.enums.h).
|
||||||
|
*/
|
||||||
static mos6502_instruction_handler instruction_handlers[] = {
|
static mos6502_instruction_handler instruction_handlers[] = {
|
||||||
INST_HANDLER(adc),
|
INST_HANDLER(adc),
|
||||||
INST_HANDLER(and),
|
INST_HANDLER(and),
|
||||||
@ -112,6 +126,11 @@ static mos6502_instruction_handler instruction_handlers[] = {
|
|||||||
INST_HANDLER(tya),
|
INST_HANDLER(tya),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we have a table that maps opcodes to the number of cycles each
|
||||||
|
* should cost. In cases where no opcode is defined, we set the number
|
||||||
|
* of cycles to zero.
|
||||||
|
*/
|
||||||
static int cycles[] = {
|
static int cycles[] = {
|
||||||
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
||||||
7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0, // 0x
|
7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0, // 0x
|
||||||
@ -185,6 +204,15 @@ mos6502_next_byte(mos6502 *cpu)
|
|||||||
return byte;
|
return byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push a _16-bit_ number to the stack. Generally speaking, only
|
||||||
|
* addresses are pushed to the stack, such that would be contained in
|
||||||
|
* the PC register (which is 16-bit).
|
||||||
|
*
|
||||||
|
* The stack is contained within a single page of memory, so you would
|
||||||
|
* be right in observing that the stack can contain at most 128, not
|
||||||
|
* 256, addresses.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
mos6502_push_stack(mos6502 *cpu, vm_16bit addr)
|
mos6502_push_stack(mos6502 *cpu, vm_16bit addr)
|
||||||
{
|
{
|
||||||
@ -201,6 +229,9 @@ mos6502_push_stack(mos6502 *cpu, vm_16bit addr)
|
|||||||
cpu->S += 2;
|
cpu->S += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pop an address from the stack and return that.
|
||||||
|
*/
|
||||||
vm_16bit
|
vm_16bit
|
||||||
mos6502_pop_stack(mos6502 *cpu)
|
mos6502_pop_stack(mos6502 *cpu)
|
||||||
{
|
{
|
||||||
@ -216,12 +247,21 @@ mos6502_pop_stack(mos6502 *cpu)
|
|||||||
vm_segment_get(cpu->memory, 0x0100 + cpu->S + 1);
|
vm_segment_get(cpu->memory, 0x0100 + cpu->S + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we set the status register to a given status value, regardless
|
||||||
|
* of its past contents.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
mos6502_set_status(mos6502 *cpu, vm_8bit status)
|
mos6502_set_status(mos6502 *cpu, vm_8bit status)
|
||||||
{
|
{
|
||||||
cpu->P = status;
|
cpu->P = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In contrast, the modify_status function will conditionally set the
|
||||||
|
* contents of certain bits, based upon the value of the operand. Those
|
||||||
|
* bits are the negative, overflow, carry, and zero flags.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
mos6502_modify_status(mos6502 *cpu, vm_8bit status, vm_8bit oper)
|
mos6502_modify_status(mos6502 *cpu, vm_8bit status, vm_8bit oper)
|
||||||
{
|
{
|
||||||
@ -254,12 +294,20 @@ mos6502_modify_status(mos6502 *cpu, vm_8bit status, vm_8bit oper)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the instruction that is mapped to a given opcode.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
mos6502_instruction(vm_8bit opcode)
|
mos6502_instruction(vm_8bit opcode)
|
||||||
{
|
{
|
||||||
return instructions[opcode];
|
return instructions[opcode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of cycles an opcode may consume. The cpu is a
|
||||||
|
* required parameter, because the number of opcodes is conditional upon
|
||||||
|
* the effective address of the instruction we're executing.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
mos6502_cycles(mos6502 *cpu, vm_8bit opcode)
|
mos6502_cycles(mos6502 *cpu, vm_8bit opcode)
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "vm_screen.h"
|
#include "vm_screen.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a new screen context. We also set the color to black.
|
||||||
|
*/
|
||||||
vm_screen_context *
|
vm_screen_context *
|
||||||
vm_screen_new_context()
|
vm_screen_new_context()
|
||||||
{
|
{
|
||||||
@ -18,12 +21,18 @@ vm_screen_new_context()
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the contents of a screen context.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
vm_screen_free_context(vm_screen_context *context)
|
vm_screen_free_context(vm_screen_context *context)
|
||||||
{
|
{
|
||||||
free(context);
|
free(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the color of a screen context to a given RGBA value.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
vm_screen_set_color(vm_screen_context *context,
|
vm_screen_set_color(vm_screen_context *context,
|
||||||
int red,
|
int red,
|
||||||
@ -37,6 +46,10 @@ vm_screen_set_color(vm_screen_context *context,
|
|||||||
context->color_alpha = alpha;
|
context->color_alpha = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw a rectangle on the screen at a given x/y position, with a given
|
||||||
|
* set of x/y dimensions, with a given screen context.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
vm_screen_draw_rect(vm_screen_context *context,
|
vm_screen_draw_rect(vm_screen_context *context,
|
||||||
int xpos,
|
int xpos,
|
||||||
|
Reference in New Issue
Block a user