-
Notifications
You must be signed in to change notification settings - Fork 0
/
CVICII.h
210 lines (187 loc) · 6.19 KB
/
CVICII.h
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//
// Created by valerino on 19/01/19.
//
#pragma once
#include <CMOS65xx.h>
#include "CCIA2.h"
#include "CPLA.h"
/**
* screen modes
* https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode
*/
#define VIC_SCREEN_MODE_CHARACTER_STANDARD 0
#define VIC_SCREEN_MODE_CHARACTER_MULTICOLOR 1
#define VIC_SCREEN_MODE_BITMAP_STANDARD 2
#define VIC_SCREEN_MODE_BITMAP_MULTICOLOR 3
#define VIC_SCREEN_MODE_EXTENDED_BACKGROUND_COLOR 4
// sizes comprensive of vblank and hblank
// http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt
#define VIC_PAL_SCREEN_W 403
#define VIC_PAL_SCREEN_H 284
#define VIC_PAL_SCANLINES 312
#define VIC_PAL_HZ 985248
#define VIC_PAL_CYCLES_PER_LINE 63
#define VIC_PAL_CYCLES_PER_BADLINE 23
/**
* registers
* https://www.c64-wiki.com/wiki/Page_208-211
*/
#define VIC_REGISTERS_START 0xd000
#define VIC_REGISTERS_END 0xd3ff
/**
* @brief defines a color in the c64 palettte
*/
typedef struct _rgbStruct {
uint8_t r;
uint8_t g;
uint8_t b;
} RgbStruct;
/**
* @brief defines a rectangle
*/
typedef struct _rect {
int firstVisibleX; // first display window column
int firstVisibleLine; // first display window row
int lastVisibleX; // last display window column
int lastVisibleLine; // last display window row
int firstVblankLine; // first row drawn at all, from the beam perspective
int lastVblankLine; // last row at all, from the beam perspective
int firstSpriteX; // this is the first column to start displaying sprites
} Rect;
/**
* @brief callback to set the pixel at the specific position
*/
typedef void (*BlitCallback)(void *thisPtr, RgbStruct *rgb, int pos);
/**
* emulates the vic-ii 6569 chip
*/
class CVICII {
friend class CDisplay;
public:
/**
* constructor
* @param cpu the cpu
* @param cia2 the CIA-2 chip
* @param pla the PLA chip
*/
CVICII(CMOS65xx *cpu, CCIA2 *cia2, CPLA *pla);
/**
* update the internal state
* @param current cycle count
* @return additional cycles used
*/
int update(long cycleCount);
/**
* read from chip memory
* @param address
* @param bt
*/
void read(uint16_t address, uint8_t *bt);
/**
* write to chip memory
* @param address
* @param bt
*/
void write(uint16_t address, uint8_t bt);
/**
* @brief hack to enable/disable hardware collisions until they're
* completely fixed (this prevents some games to work at all, i.e.
* hunchback)
*
* @param enableSpriteSprite enable sprite-sprite collision (default)
* @param enableSpriteBackground enable sprite-background collision
* (default)
*/
void setCollisionHandling(bool enableSpriteSprite,
bool enableBackgroundSprite);
protected:
/**
* set blitting callback
* @param display opaque pointer to the display handler
* @param cb callback to be called when blitting a pixel
*/
void setBlitCallback(void *display, BlitCallback cb);
private:
CMOS65xx *_cpu = nullptr;
void *_displayObj = nullptr;
int _prevCycles = 0;
uint16_t _rasterIrqLine = 0;
int _scrollX = 0;
int _scrollY = 0;
bool _CSEL = false;
bool _RSEL = false;
bool _DEN = false;
uint8_t _regM[8 * 2] = {0}; // 8 hardware sprites coordinates registers X/Y
// (M0X,M0Y ... M7X,M7Y)
uint8_t _regMSBX = 0;
uint8_t _regCR1 = 0;
uint16_t _regRASTER = 0;
uint8_t _regLP[2] = {0};
uint8_t _regSpriteEnabled = 0;
uint8_t _regCR2 = 0;
uint8_t _regSpriteYExpansion = 0;
uint8_t _regMemoryPointers = 1;
uint8_t _regInterrupt = 0;
uint8_t _regInterruptEnabled = 0;
uint8_t _regSpriteDataPriority = 0;
uint8_t _regSpriteMultiColor = 0;
uint8_t _regSpriteXExpansion = 0;
uint8_t _regSpriteSpriteCollision = 0;
uint8_t _regSpriteBckCollision = 0;
uint8_t _regBorderColor = 0;
uint8_t _regBC[4] = {0}; // 4 background colors (registers B0C ... B3C)
uint8_t _regMM[2] = {0}; // sprite multicolor (registers MM0-MM1)
uint8_t _regMC[8] = {
0}; // sprite colors for hw sprites 0..7 (registers M0C ... M7C)
BlitCallback _cb = nullptr;
CCIA2 *_cia2 = nullptr;
RgbStruct _palette[16] = {0};
uint16_t _charsetAddress = 0;
uint16_t _screenAddress = 0;
uint16_t _bitmapAddress = 0;
int _screenMode = VIC_SCREEN_MODE_CHARACTER_STANDARD;
CPLA *_pla = nullptr;
bool _sprSprHwCollisionEnabled = true;
bool _sprBckHwCollisionEnabled = true;
uint16_t handleShadowAddress(uint16_t address);
bool isSpriteEnabled(int idx);
bool isSpriteMulticolor(int idx);
bool isSpriteYExpanded(int idx);
bool isSpriteXExpanded(int idx);
void setSpriteCoordinate(int idx, uint8_t val);
uint8_t getSpriteCoordinate(int idx);
void setSpriteColor(int idx, uint8_t val);
uint8_t getSpriteColor(int idx);
void setSpriteMulticolor(int idx, uint8_t val);
uint8_t getSpriteMulticolor(int idx);
uint8_t getBackgroundColor(int idx);
void setBackgoundColor(int idx, uint8_t val);
uint16_t getSpriteXCoordinate(int idx);
uint8_t getSpriteYCoordinate(int idx);
void drawBorder(int rasterLine);
void drawCharacterMode(int rasterLine);
void drawSprites(int rasterLine);
void drawSpriteMulticolor(int rasterLine, int idx, int x, int row);
void blit(int x, int y, RgbStruct *rgb);
void initPalette();
void setScreenMode();
void drawSprite(int rasterLine, int idx, int x, int row);
bool isSpriteDrawingOnBorder(int x, int y);
uint16_t getSpriteDataAddress(int idx);
void getScreenLimits(Rect *limits);
int getCurrentRasterLine();
void setCurrentRasterLine(int line);
void drawBitmapMode(int rasterLine);
uint8_t getScreenCode(int x, int y);
uint8_t getScreenColor(int x, int y);
uint8_t getCharacterData(int screenCode, int charRow);
uint8_t getBitmapData(int x, int y, int bitmapRow);
void checkSpriteSpriteCollision(int idx, int x, int y);
void checkSpriteBackgroundCollision(int x, int y);
void readVICByte(uint16_t address, uint8_t *bt);
uint8_t getBorderColor();
uint8_t getCR2();
uint8_t getInterruptLatch();
uint8_t getInterruptEnabled();
uint8_t getMemoryPointers();
};