summaryrefslogtreecommitdiff
path: root/applesystem.h
blob: a26aff7d0f2662a0e5c46f96ebe5f6f102c36858 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
typedef unsigned char byte;
typedef unsigned short address;
byte acc, X, Y, P = 0x00;
address S = 0x0000;
byte Memory[4096]; // TO DO. Add expansion capability to memory.

/*
To Do.
	+ Find variables better passed as pointers instead
	+ Clean up this messy code
*/


//	FLAGS
const byte flag_N = 0x80;	// Negative (Note that byte cast is necessary here only)
const byte flag_V = 0x40;	// Overflow
const byte flag_B = 0x10;	// BRK command
const byte flag_D = 0x08;	// Decimal mode
const byte flag_I = 0x04;	// IRQ disable
const byte flag_Z = 0x02;	// Zero
const byte flag_C = 0x01;	// Carry

byte getFlag(byte flag) {
	return ((P & flag) == flag) ? 1 : 0;
}

void setFlag(byte flag, int x) { //OVERLOAD TO ACCEPT INT AS WELL
	if (x == 1){
		if ((P & flag) == 0x0)	P += flag;
	}else if (x == 0){
		if ((P & flag) == flag)	P -= flag;
	}
	else{
		fprintf(stderr, "setFlag() passed arg neither 0 or 1");
	}
}

void flagSet(byte flag){
	P |= flag;
}

void flagClear(byte flag){
	P &= ~flag
}


//	BCD

byte toBCD(byte x){
	if (x < 100){
		byte a = ((x / 10) << 4);
		byte b = (x % 10);
		return (a + b);
	}
	else{
		fprintf(stderr, "Number greater than 99 passed to toBCD()");
	}
}

byte fromBCD(byte x){
	byte a = ((x >> 4) * 10);
	byte b = (x & 0xF);
	return (a + b);
}

// addBCD()



// Class of instructions
//each one has every type of addressing mode, inherited from a base class.
// the different addressing modes will be distinguished when the bytecode is called, it will run the instructions function with a selection for the 
/* example

Immediate     ADC #$44      $69  2   2
instruction(0x69); -> ADC({enum for immediate}); 

Zero Page     ADC $44       $65  2   3
instruction(0x65); -> ADC({enum for Zero Page}); 
*/
// Set particular flags
// Functions which quickly set specific flags that are straightforward checks, and are repeated often.
void setFlagN(byte x){
	if (x ^ flag_N == flag_N){
		setFlag(flag_N, 1);
	}else{ //not sure if this should be present, I think it is
		setFlag(flag_N, 0);
	}
}

//Perform prior to any changes
void setFlagV(byte x, byte y){
	if ((x & flag_N) == (y & flag_N)){
		if (((x + y) & (flag_N ^ 0xFF)) > 0x7F) setFlag(flag_V, 1);
		else setFlag(flag_V, 0);
	}else{
		if (((x - y) & (flag_N ^ 0xFF)) > 0x7F) setFlag(flag_V, 1);
		else setFlag(flag_V, 0);
	}
}
/*void setFlagB(){ //WORK ON
	setFlag(flag_B, 1);
}*/ //Dont really need since its dependent on the BRK insturction
/*void setFlagD(){
	setFlag(flag_D, 1);
}*/
void setFlagI(){ //WORK ON
	setFlag(flag_Z, 1);
}
void setFlagZ(int x){
	if (x == 0) {
		setFlag(flag_Z, 1);
	}
}
//Only 6 instructions, 2 not including stack instructions, use the carry flag.
/*void setFlagC(){ // NOTE. Must make setFlagC functional with independence. Look into carrying on 6502
	setFlag(flag_Z, 1);
}*/