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
|
#ifndef MAIN_H
#define MAIN_H
#include <limits.h>
#include <stdbool.h>
#include "lookup.h"
bool render = false;
uint8_t V[16];//all the registers
#define WIDTH 64
#define HEIGHT 32
#define BITMASK(b) (1 << ((b) % CHAR_BIT))
#define BITSLOT(b) ((b) / CHAR_BIT)
#define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
#define BITCLEAR(a, b) ((a)[BITSLOT(b)] &= ~BITMASK(b))
#define BITTEST(a, b) ((a)[BITSLOT(b)] & BITMASK(b))
//bittest that works with pointers
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
char *program; //program is defined here so it can be accessed in main.h
char *I; //left wild to be set later
int *pixels = NULL;//used SQL pixel setting
int returnPos[12];//the position to return to when the end of a subroute is reached (e.g. 0x00EE is reached). There's meant to be a 48 byte stack, but as on the COSMAC VIP there was 12, we do that.
//value of lower four bits of 8 bit string
int lowerFour(char s[])
{
return s[0] & 0x0F;
}
//value of upper four bits of 8 bit string
int upperFour(char s[])
{
return (s[0] & 0xF0) >> 4;
}
//Draws a sprite at coordinate (VX, VY) that has a width of 8 pixels and a height of N
//pixels. Each row of 8 pixels is read as bit-coded starting from memory location I;
//I value doesn’t change after the execution of this instruction.
//As described above, VF is set to 1 if any screen pixels are flipped from set to unset
//when the sprite is drawn, and to 0 if that doesn’t happen
int draw(uint8_t VX, uint8_t VY, int N)
{
render = true;
int bitPosition;//the bits read from I need to be bittested from bit 7 to 0. x can't be used since it goes from 0 to 7.
V[0xF] = 0;//0 by default, since if we don't unset pixels, then VF equals 0
bitPosition = 8;
for (int x=0; x<8; ++x)
{
--bitPosition;
if (bitPosition == -1){printf("No\n"); exit(1);}
for (int y=0; y<N; ++y)
{
//only draw if place to draw is within bounds
if ((VX+x < WIDTH) && (VY+y < HEIGHT))//position of x is correct
{
if(CHECK_BIT(*(I+y),bitPosition))//draw white xor if bit in I+y is set, do not draw anything if pixel is black though
{
if (pixels[display[VY+y][VX+x]] == 0xFFFFFFFF){V[0xF] = 1;}//set VF to 1 if pixel to draw is already set
pixels[display[VY+y][VX+x]] ^= 0xFFFFFFFF;//draw with XOR
}
}
else
{
//use modulus make out of range writes start again at 0
if(CHECK_BIT(*(I+y),bitPosition))//draw white xor if bit in I+y is set, do not draw anything if pixel is black though
{
if (pixels[display[(VY+y)%HEIGHT][(VX+x)%WIDTH]] == 0xFFFFFFFF){V[0xF] = 1;}
pixels[display[(VY+y)%HEIGHT][(VX+x)%WIDTH]] ^= 0xFFFFFFFF;
}
}
}
}
}
void display_clear()
{
render = true;
for (int x = 0; x<WIDTH; ++x)
{
for (int y = 0; y<HEIGHT; ++y)
{
pixels[display[y][x]] = 0x00000000;
}
}
}
#endif
|