2 EPOCH Super Cassette Vision Emulator 'eSCV'
4 Author : Takeda.Toshiya
11 #include "../upd7801.h"
15 static const scrntype_t palette_pc[16] = {
17 RGB_COLOR( 0, 90,156), RGB_COLOR( 0, 0, 0), RGB_COLOR( 58,148,255), RGB_COLOR( 0, 0,255),
18 RGB_COLOR( 16,214, 0), RGB_COLOR( 66,255, 16), RGB_COLOR(123,230,197), RGB_COLOR( 0,173, 0),
19 RGB_COLOR(255, 41,148), RGB_COLOR(255, 49, 16), RGB_COLOR(255, 58,255), RGB_COLOR(239,156,255),
20 RGB_COLOR(255,206, 33), RGB_COLOR( 74,123, 16), RGB_COLOR(165,148,165), RGB_COLOR(255,255,255)
22 RGB_COLOR( 0, 90,156), RGB_COLOR( 0, 0, 0), RGB_COLOR( 0, 58,255), RGB_COLOR( 0, 0,255),
23 RGB_COLOR( 0,255, 0), RGB_COLOR( 58,255, 90), RGB_COLOR( 0,255,255), RGB_COLOR( 0,255, 0),
24 RGB_COLOR(255, 58,156), RGB_COLOR(255,156,156), RGB_COLOR(255, 58,255), RGB_COLOR(255,156,255),
25 RGB_COLOR(255,255, 90), RGB_COLOR(123,156, 0), RGB_COLOR(189,189,189), RGB_COLOR(255,255,255)
30 // table analyzed by Enri
31 static const uint8_t color_pair0[16] = {0x0, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x1, 0x1};
32 static const uint8_t color_pair1[16] = {0x0, 0x1, 0x8, 0xb, 0x2, 0x3, 0xa, 0x9, 0x4, 0x5, 0xc, 0xd, 0x6, 0x7, 0xe, 0xf};
34 static const uint8_t color_pair0[16] = {0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1};
35 static const uint8_t color_pair1[16] = {0x0, 0x1, 0x8, 0x9, 0x2, 0x3, 0xa, 0xb, 0x4, 0x5, 0xc, 0xd, 0x6, 0x7, 0xe, 0xf};
38 static const uint8_t symbol[32][8] = {
39 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x00,0x02,0x7a,0x84,0x84,0x7a,0x00,0x00},
40 {0x00,0x3c,0x42,0x7c,0x42,0x7c,0x40,0x40},{0x00,0x62,0x94,0x08,0x08,0x08,0x00,0x00},
41 {0x00,0xfc,0x50,0x50,0x52,0x8c,0x00,0x00},{0xfe,0x82,0x60,0x10,0x60,0x82,0xfe,0x00},
42 {0x38,0x44,0x82,0x82,0x82,0x44,0xc6,0x00},{0x10,0x7c,0xfe,0xfe,0xfe,0x10,0x38,0x00},
43 {0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x10,0x00},{0x10,0x10,0x38,0xfe,0x38,0x10,0x10,0x00},
44 {0x10,0x7c,0x92,0xfe,0x92,0x10,0x38,0x00},{0x38,0x44,0xba,0xa2,0xba,0x44,0x38,0x00},
45 {0x80,0x80,0x88,0x44,0x3e,0x04,0x08,0x00},{0x02,0x02,0x22,0x44,0xf8,0x40,0x20,0x00},
46 {0x10,0x00,0x00,0xfe,0x00,0x00,0x10,0x00},{0x00,0x80,0x40,0x20,0x10,0x08,0x04,0x00},
47 {0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00},{0x7c,0xfe,0xfe,0xfe,0xfe,0xfe,0x7c,0x00},
48 {0x7c,0x82,0xba,0xba,0xba,0x82,0x7c,0x00},{0xfe,0x82,0x82,0x82,0x82,0x82,0xfe,0x00},
49 {0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55},{0xff,0x80,0x80,0x80,0x80,0x80,0x80,0x80},
50 {0xff,0x01,0x01,0x01,0x01,0x01,0x01,0x01},{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xff},
51 {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xff},{0xfe,0x00,0xfe,0x10,0x10,0x10,0x10,0x00},
52 {0x18,0x14,0x12,0x12,0x72,0xf0,0x60,0x00},{0x18,0x14,0x12,0x12,0x72,0x90,0x60,0x00},
53 {0x10,0x08,0x04,0xfe,0x04,0x08,0x10,0x00},{0x10,0x20,0x40,0xfe,0x40,0x20,0x10,0x00},
54 {0x10,0x38,0x54,0x92,0x10,0x10,0x10,0x00},{0x10,0x10,0x10,0x92,0x54,0x38,0x10,0x00}
57 void VDP::initialize()
60 for(int i = 0, c = 0x20, p = 0; i < 3; i++, c += 32) {
61 for(int j = 0; j < 16; j++) {
62 for(int k = 0; k < 8; k += 2) {
63 uint8_t d0 = font_ptr[p++];
64 uint8_t d1 = font_ptr[p++];
65 uint8_t d2 = font_ptr[p++];
66 uint8_t d3 = font_ptr[p++];
68 font[c + j ][k ] = (d0 & 0xf0) | (d1 >> 4);
69 font[c + j + 16][k ] = (d2 & 0xf0) | (d3 >> 4);
70 font[c + j ][k + 1] = (d0 << 4) | (d1 & 0x0f);
71 font[c + j + 16][k + 1] = (d2 << 4) | (d3 & 0x0f);
75 memcpy(font, symbol, sizeof(symbol));
76 memcpy(font[0xb], font[0x60], 8); // copyright mark
78 // register event to interrupt
79 register_vline_event(this);
82 void VDP::event_vline(int v, int clock)
85 d_cpu->write_signal(SIG_UPD7801_INTF2, 1, 1);
87 d_cpu->write_signal(SIG_UPD7801_INTF2, 0, 1);
91 void VDP::draw_screen()
93 // get vdc control params
100 memset(text, vdc1 & 0xf, sizeof(text));
103 // draw sprite screen
104 memset(sprite, 0, sizeof(sprite));
106 draw_sprite_screen();
110 int ty = ((vdc0 & 0xf7) == 0x17 && (vdc2 & 0xef) == 0x4f) ? 32 : 0;
111 uint16_t back = palette_pc[vdc1 & 0xf];
113 for(int y = 0; y < ty; y++) {
114 // patch for nekketsu kung-fu road
115 scrntype_t* d = emu->get_screen_buffer(y);
116 uint8_t* t = &text[y + 23][24];
118 for(int x = 0; x < SCREEN_WIDTH; x++) {
119 d[x] = palette_pc[t[x]];
122 for(int y = ty; y < SCREEN_HEIGHT; y++) {
123 scrntype_t* d = emu->get_screen_buffer(y);
124 uint8_t* s = &sprite[y + 21][28];
125 uint8_t* t = &text[y + 23][24];
127 for(int x = 0; x < SCREEN_WIDTH; x++) {
128 d[x] = palette_pc[s[x] ? s[x] : t[x]];
133 void VDP::draw_text_screen()
135 int xmax = (vdc2 & 0xf) * 2;
136 //xmax = xmax ? xmax : 32;
137 int ymax = vdc2 >> 4;
138 int xs = (vdc0 & 0x40) ? xmax : 0;
139 int xe = (vdc0 & 0x40) ? 32 : xmax;
140 int ys = (vdc0 & 0x80) ? ymax : 0;
141 int ye = (vdc0 & 0x80) ? 16 : ymax;
143 uint8_t ct = vdc3 >> 4;
144 uint8_t cb = vdc3 & 0xf;
145 uint8_t cg = vdc1 >> 4;
147 for(int y = 1; y < 16; y++) {
148 bool t = (ys <= y && y < ye);
151 for(int x = 2; x < 29; x++) {
152 if(t && (xs <= x && x < xe)) {
154 uint8_t data = (x < 26) ? (vram1[y32 + x] & 0x7f) : 0;
155 draw_text(x, y, data, ct, cb);
156 } else if((vdc0 & 3) == 1) {
158 uint8_t data = vram1[y32 + x];
159 draw_graph(x, y, data, cg);
160 } else if((vdc0 & 3) == 3) {
162 uint8_t data = vram1[y32 + x];
163 draw_block(x, y, data);
169 void VDP::draw_text(int dx, int dy, uint8_t data, uint8_t tcol, uint8_t bcol)
171 int dx8 = dx << 3, dy16 = dy << 4;
173 for(int l = 0; l < 8 && data; l++) {
174 uint8_t* dest = &text[dy16 + l][dx8];
175 uint8_t pat = font[data][l];
177 dest[0] = (pat & 0x80) ? tcol : bcol;
178 dest[1] = (pat & 0x40) ? tcol : bcol;
179 dest[2] = (pat & 0x20) ? tcol : bcol;
180 dest[3] = (pat & 0x10) ? tcol : bcol;
181 dest[4] = (pat & 0x08) ? tcol : bcol;
182 dest[5] = (pat & 0x04) ? tcol : bcol;
183 dest[6] = (pat & 0x02) ? tcol : bcol;
184 dest[7] = (pat & 0x01) ? tcol : bcol;
186 for(int l = (data ? 8 : 0); l < 16; l++) {
187 memset(&text[dy16 + l][dx8], bcol, 8);
191 void VDP::draw_block(int dx, int dy, uint8_t data)
193 int dx8 = dx << 3, dy16 = dy << 4;
194 uint8_t cu = data >> 4, cl = data & 0xf;
197 for(int l = 0; l < 8; l++) {
198 memset(&text[dy16 + l][dx8], cu, 8);
202 for(int l = 8; l < 16; l++) {
203 memset(&text[dy16 + l][dx8], cl, 8);
208 void VDP::draw_graph(int dx, int dy, uint8_t data, uint8_t col)
210 int dx8l = dx << 3, dx8r = (dx << 3) + 4, dy16 = dy << 4;
213 for(int l = 0; l < 4; l++) {
214 memset(&text[dy16 + l][dx8l], col, 4);
218 for(int l = 0; l < 4; l++) {
219 memset(&text[dy16 + l][dx8r], col, 4);
223 for(int l = 4; l < 8; l++) {
224 memset(&text[dy16 + l][dx8l], col, 4);
228 for(int l = 4; l < 8; l++) {
229 memset(&text[dy16 + l][dx8r], col, 4);
233 for(int l = 8; l < 12; l++) {
234 memset(&text[dy16 + l][dx8l], col, 4);
238 for(int l = 8; l < 12; l++) {
239 memset(&text[dy16 + l][dx8r], col, 4);
243 for(int l = 12; l < 16; l++) {
244 memset(&text[dy16 + l][dx8l], col, 4);
248 for(int l = 12; l < 16; l++) {
249 memset(&text[dy16 + l][dx8r], col, 4);
254 void VDP::draw_sprite_screen()
256 for(int index = 0; index < 128; index++) {
257 uint8_t atb0 = vram1[0x200 + (index << 2)];
258 uint8_t atb1 = vram1[0x201 + (index << 2)];
259 uint8_t atb2 = vram1[0x202 + (index << 2)];
260 uint8_t atb3 = vram1[0x203 + (index << 2)];
262 int dx = atb2 & 0xfe;
263 int dy = atb0 & 0xfe;
264 bool conx = ((atb2 & 1) != 0);
265 bool cony = ((atb0 & 1) != 0);
266 uint8_t col0 = atb1 & 0xf;
269 int sy = atb1 >> 4, ey = 8;
271 // half/quarter sprite
275 dy = !cony ? dy : dy - 8;
280 dx = !conx ? dx : dx - 8;
286 if((index & 0x20) && (vdc0 & 0x20)) {
288 uint8_t col1 = (index & 0x40) ? color_pair1[col0] : color_pair0[col0];
289 int no1 = atb3, no2 = atb3 ^ ((conx ? 8 : 0) | (cony ? 1 : 0));
291 draw_sprite(dx, dy, sx, ex, sy, ey, no1, col0);
293 draw_sprite(dx, dy, sx, ex, sy, ey, no2, col1);
297 int no1 = atb3, no2 = atb3 | 1, no3 = atb3 | 8, no4 = atb3 | 9;
299 draw_sprite(dx, dy, sx, ex, sy, ey, no1, col0);
301 draw_sprite(dx, dy + 16, sx, ex, sy - 8, 8, no2, col0);
304 draw_sprite(dx + 16, dy, 0, 4, sy, ey, no3, col0);
307 draw_sprite(dx + 16, dy + 16, 0, 4, sy - 8, 8, no4, col0);
313 void VDP::draw_sprite(int dx, int dy, int sx, int ex, int sy, int ey, int no, uint8_t col)
315 // color #0 is transparent
319 for(int y = (sy < 0 ? 0 : sy), no32 = no << 5; y < ey; y++) {
320 int y2u = (y << 1) + dy, y2l = (y << 1) + dy + 1, y4 = (y << 2) + no32;
322 for(int x = sx; x < ex; x++) {
323 int x4 = dx + (x << 2);
324 uint8_t* du = &sprite[y2u][x4];
325 uint8_t* dl = &sprite[y2l][x4];
326 uint8_t p = vram0[y4 + x];
328 if(p & 0x80) du[0] = col;
329 if(p & 0x40) du[1] = col;
330 if(p & 0x20) du[2] = col;
331 if(p & 0x10) du[3] = col;
332 if(p & 0x08) dl[0] = col;
333 if(p & 0x04) dl[1] = col;
334 if(p & 0x02) dl[2] = col;
335 if(p & 0x01) dl[3] = col;
340 #define STATE_VERSION 1
343 bool VDP::process_state(FILEIO* state_fio, bool loading)
345 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
348 if(!state_fio->StateCheckInt32(this_device_id)) {
351 state_fio->StateValue(vdc0);
352 state_fio->StateValue(vdc1);
353 state_fio->StateValue(vdc2);
354 state_fio->StateValue(vdc3);