Skip to content

Commit bab93cf

Browse files
committed
Switched to v4.1.0 rendering
1 parent b9f388e commit bab93cf

14 files changed

+3327
-856
lines changed

4.1.0/crtc.c

+278
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/* Caprice32 - Amstrad CPC Emulator
2+
(c) Copyright 1997-2004 Ulrich Doewich
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program; if not, write to the Free Software
16+
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17+
*/
18+
19+
/* Hitachi HD6845S CRT Controller (CRTC Type 0) emulation
20+
(c) Copyright 1997-2004 Ulrich Doewich
21+
22+
Oct 16, 2000 - 23:12 started conversion from assembly to C
23+
Oct 17, 2000 - 19:25 finished converting main CRTC update loop
24+
Oct 17, 2000 - 22:04 added framework for mode draw handlers
25+
Oct 25, 2000 - 22:03 changed all CRTC counters to be only 8 bits wide; fixed address calculation
26+
Oct 30, 2000 - 19:03 fixed CPC screen address line advancement (test should have been for a _reset_ bit!)
27+
Mar 20, 2001 - 16:00 added draw_mode2
28+
Jun 20, 2001 - 23:24 added drawing routines for 32bpp video modes
29+
Jul 04, 2001 - 22:28 16bpp rendering; updated 8bpp code with VDU visible region limiting
30+
Sep 26, 2002 - 22:39 moved rendering code to separate files; added line doubling (in software) code
31+
Oct 07, 2002 - 21:58 removed the CPC.scr_max test in write_video_data; added support for variable line spacing
32+
33+
May 23, 2004 - 17:38 added some preliminary VDU frame cropping to reduce the amount of data written to the video buffer
34+
May 24, 2004 - 00:44 moved the write_video_data code into the body of access_video_memory
35+
*/
36+
37+
#include "cap32.h"
38+
#include "crtc.h"
39+
#include "z80.h"
40+
41+
extern t_CPC CPC;
42+
extern t_CRTC CRTC;
43+
extern t_GateArray GateArray;
44+
extern t_VDU VDU;
45+
extern t_z80regs z80;
46+
47+
extern byte *pbRAM;
48+
extern byte mode0_table[512], mode1_table[1024];
49+
50+
#ifdef DEBUG_CRTC
51+
extern FILE *pfoDebug;
52+
#endif
53+
54+
55+
56+
void crtc_cycle(int repeat_count)
57+
{
58+
register byte char_count, line_count, raster_count;
59+
60+
do {
61+
char_count = CRTC.char_count;
62+
line_count = CRTC.line_count;
63+
raster_count = CRTC.raster_count;
64+
char_count++; // update character count (cc)
65+
VDU.char_count++;
66+
if (CRTC.flags & HT_flag) { // reached horizontal total on last cc?
67+
CRTC.flags &= ~HT_flag;
68+
CRTC.hsw_active = CRTC.hsw;
69+
VDU.hsw_active = VDU.hsw;
70+
char_count = 0; // reset cc
71+
// next raster ----------------------------------------------------------------
72+
raster_count += 8; // advance rc by one
73+
if (CRTC.flags & VS_flag) { // in VSYNC?
74+
CRTC.vsw_count++; // update width counter
75+
if (CRTC.vsw_count >= CRTC.vsw) { // reached end of VSYNC?
76+
CRTC.flags = (CRTC.flags & ~VS_flag) | VSf_flag; // reset VSYNC, set 'just finished'
77+
}
78+
}
79+
if (CRTC.flags & MR_flag) { // reached maximum raster address on last rc?
80+
CRTC.flags &= ~MR_flag;
81+
raster_count = 0; // reset rc
82+
if (!(CRTC.flags & HDT_flag)) { // HDISPTMG still on (i.e. R01 > R00)?
83+
CRTC.addr += CRTC.last_hdisp * 2; // advance CPC screen address to next line
84+
}
85+
line_count++; // update line count
86+
line_count &= 127; // limit to 7 bits
87+
}
88+
if (CRTC.vt_adjust_count) { // vertical total adjust active?
89+
if (--CRTC.vt_adjust_count == 0) { // done with vta?
90+
CRTC.flags = (CRTC.flags & ~VSf_flag) | VDT_flag; // enable VDISPTMG
91+
raster_count = 0; // reset rc
92+
line_count = 0; // reset lc
93+
CRTC.addr = CRTC.requested_addr; // update start of CPC screen address
94+
}
95+
}
96+
if (CRTC.flags & VT_flag) { // reached vertical total on last lc?
97+
CRTC.flags &= ~VT_flag;
98+
if (CRTC.vt_adjust) { // do a vertical total adjust?
99+
CRTC.vt_adjust_count = CRTC.vt_adjust; // init vta counter
100+
} else {
101+
CRTC.flags = (CRTC.flags & ~VSf_flag) | VDT_flag; // enable VDISPTMG
102+
raster_count = 0; // reset rc
103+
line_count = 0; // reset lc
104+
CRTC.addr = CRTC.requested_addr; // update start of CPC screen address
105+
}
106+
}
107+
if (raster_count == CRTC.max_raster) { // rc = maximum raster address?
108+
CRTC.flags |= MR_flag; // process max raster address on next rc
109+
if (!CRTC.vt_adjust_count) { // no vertical total adjust?
110+
if (line_count == CRTC.registers[4]) { // lc = vertical total?
111+
CRTC.flags |= VT_flag; // takes effect on next lc
112+
}
113+
}
114+
}
115+
if (line_count == CRTC.registers[6]) { // lc = vertical displayed?
116+
CRTC.flags &= ~VDT_flag; // disable VDISPTMG
117+
}
118+
if (line_count == CRTC.registers[7]) { // lc = vertical sync position?
119+
if (!(CRTC.flags & (VSf_flag | VS_flag))) { // not in VSYNC?
120+
CRTC.flags |= VS_flag;
121+
CRTC.vsw_count = 0; // clear vsw counter
122+
VDU.vdelay = 2; // GA delays vsync by 2 scanlines
123+
VDU.vsw_count = 4; // GA vsync is always 4 scanlines long
124+
GateArray.int_delay = 2; // arm GA two scanlines interrupt delay
125+
}
126+
}
127+
// ----------------------------------------------------------------------------
128+
CRTC.flags |= HDT_flag; // enable horizontal display
129+
}
130+
if (char_count == CRTC.registers[0]) { // cc = horizontal total?
131+
CRTC.flags |= HT_flag; // takes effect on next cc
132+
}
133+
if (char_count == CRTC.registers[1]) { // cc = horizontal displayed?
134+
CRTC.flags &= ~HDT_flag; // disable horizontal display
135+
CRTC.last_hdisp = CRTC.registers[1]; // save width for line advancement
136+
}
137+
if (CRTC.flags & HS_flag) { // in horizontal sync?
138+
// check hsw ------------------------------------------------------------------
139+
if (VDU.hdelay == 2) { // ready to trigger VDU HSYNC?
140+
if (--VDU.hsw_count == 0) {
141+
if (CPC.scr_line++ < CPC_SCR_HEIGHT) {
142+
if (VDU.vcount) { // in the visible portion of the screen?
143+
CPC.scr_base += CPC.scr_line_offs; // advance to next line
144+
}
145+
}
146+
CPC.scr_offs = 0;
147+
VDU.char_count = 0;
148+
149+
/* if (VDU.vcount) { // in the visible portion of the screen?
150+
VDU.vcount--;
151+
} else if (CPC.scr_line == VDU.vtestoffset) {
152+
VDU.vcount = VDU.vcountinit;
153+
}
154+
*/ VDU.hdelay++; // prevent reentry
155+
}
156+
} else {
157+
VDU.hdelay++; // update delay counter
158+
}
159+
if (--CRTC.hsw_count == 0) { // end of HSYNC?
160+
// hsw end --------------------------------------------------------------------
161+
CRTC.flags &= ~HS_flag; // reset HSYNC
162+
GateArray.scr_mode = GateArray.requested_scr_mode; // execute mode change
163+
VDU.scanline++;
164+
if (VDU.vdelay) { // monitor delaying VSYNC?
165+
VDU.vdelay--;
166+
}
167+
if (VDU.vdelay == 0) { // enter monitor VSYNC?
168+
if (VDU.vsw_count) { // still in monitor VSYNC?
169+
if (--VDU.vsw_count == 0) { // done with monitor VSYNC?
170+
if (VDU.scanline > VDU.scanline_min) { // above minimum scanline count?
171+
CPC.scr_offs = 0;
172+
CPC.scr_line = 0;
173+
VDU.frame_completed = 1; // force exit of emulation loop
174+
}
175+
}
176+
}
177+
}
178+
// GA interrupt trigger -------------------------------------------------------
179+
GateArray.sl_count++; // update GA scanline counter
180+
if (GateArray.int_delay) { // delay on VSYNC?
181+
if (--GateArray.int_delay == 0) { // delay expired?
182+
if (GateArray.sl_count >= 32) { // counter above save margin?
183+
z80.int_pending = 1; // queue interrupt
184+
GateArray.sl_count = 0; // clear counter
185+
} else {
186+
GateArray.sl_count = 0; // clear counter
187+
}
188+
}
189+
}
190+
if (GateArray.sl_count == 52) { // trigger interrupt?
191+
z80.int_pending = 1; // queue interrupt
192+
GateArray.sl_count = 0; // clear counter
193+
}
194+
}
195+
}
196+
// ----------------------------------------------------------------------------
197+
if (char_count == CRTC.registers[2]) { // cc = horizontal sync position?
198+
if (CRTC.hsw_active) { // allow HSYNCs?
199+
CRTC.flags |= HS_flag; // set HSYNC
200+
CRTC.hsw_count = CRTC.hsw_active; // load hsw counter
201+
VDU.hdelay = 0; // clear VDU 2 chars HSYNC delay
202+
VDU.hsw_count = VDU.hsw_active; // load VDU hsw counter
203+
}
204+
}
205+
CRTC.char_count = char_count; // store cc
206+
CRTC.line_count = line_count; // store lc
207+
CRTC.raster_count = raster_count; // store rc
208+
209+
{
210+
reg_pair addr;
211+
addr.d = char_count;
212+
addr.d = (addr.d * 2) + CRTC.addr; // cc x2 + CPC screen memory address
213+
if (addr.b.h & 0x20) { // 32K screen?
214+
addr.b.h += 0x40; // advance to next 16K segment
215+
}
216+
addr.b.h &= 0xc7; // apply 11000111 mask
217+
addr.b.h |= (raster_count & 0x38); // insert rc, masked with 00111000
218+
219+
#ifndef DEBUG_NO_VIDEO
220+
if (VDU.hcount) {
221+
if ((CRTC.flags & (HDT_flag | VDT_flag)) == (HDT_flag | VDT_flag)) { // DISPTMG enabled?
222+
if (CRTC.skew) {
223+
CRTC.skew--;
224+
GateArray.scr_border();
225+
} else {
226+
GateArray.scr_mode(addr.w.l); // call apropriate mode handler
227+
}
228+
} else {
229+
GateArray.scr_border();
230+
}
231+
VDU.hcount--;
232+
} else {
233+
if (VDU.char_count == VDU.hstart) {
234+
if (VDU.vcount) {
235+
VDU.hcount = VDU.hwidth;
236+
VDU.vcount--;
237+
} else {
238+
if (CPC.scr_line == VDU.vstart) {
239+
VDU.vcount = VDU.vheight;
240+
}
241+
}
242+
}
243+
}
244+
#endif
245+
246+
#ifdef DEBUG_CRTC
247+
fprintf(pfoDebug, "%04x | ", addr.w.l);
248+
#endif
249+
}
250+
251+
#ifdef DEBUG_CRTC
252+
{
253+
int n, f;
254+
char str[16];
255+
256+
strcpy(str, "vhddHVMa");
257+
for (n = 0, f = CRTC.flags; n < 8; n++, f >>= 1) {
258+
if (!(f & 1)) {
259+
str[n] = '.';
260+
}
261+
}
262+
fprintf(pfoDebug, "CC:%3d RC:%2d LC:%2d - HSWC:%2d VSWC:%2d - %s | %d\r\n", CRTC.char_count,
263+
CRTC.raster_count>>3, CRTC.line_count, CRTC.hsw_count, CRTC.vsw_count, str, (int)(CPC.scr_base+CPC.scr_offs));
264+
}
265+
#endif
266+
267+
} while (--repeat_count);
268+
}
269+
270+
271+
272+
#include "draw_8bpp.c"
273+
274+
#include "draw_16bpp.c"
275+
276+
#include "draw_24bpp.c"
277+
278+
#include "draw_32bpp.c"

4.1.0/crtc.h

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* Caprice32 - Amstrad CPC Emulator
2+
(c) Copyright 1997-2004 Ulrich Doewich
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program; if not, write to the Free Software
16+
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17+
*/
18+
19+
#ifndef CRTC_H
20+
#define CRTC_H
21+
22+
#include "z80.h"
23+
24+
void crtc_cycle(int repeat_count);
25+
26+
void draw8bpp_border(void);
27+
void draw8bpp_mode0(dword addr);
28+
void draw8bpp_mode1(dword addr);
29+
void draw8bpp_mode2(dword addr);
30+
void draw8bpp_border_double(void);
31+
void draw8bpp_mode0_double(dword addr);
32+
void draw8bpp_mode1_double(dword addr);
33+
void draw8bpp_mode2_double(dword addr);
34+
void draw8bpp_border_half(void);
35+
void draw8bpp_mode0_half(dword addr);
36+
void draw8bpp_mode1_half(dword addr);
37+
void draw8bpp_mode2_half(dword addr);
38+
39+
void draw16bpp_border(void);
40+
void draw16bpp_mode0(dword addr);
41+
void draw16bpp_mode1(dword addr);
42+
void draw16bpp_mode2(dword addr);
43+
void draw16bpp_border_double(void);
44+
void draw16bpp_mode0_double(dword addr);
45+
void draw16bpp_mode1_double(dword addr);
46+
void draw16bpp_mode2_double(dword addr);
47+
void draw16bpp_border_half(void);
48+
void draw16bpp_mode0_half(dword addr);
49+
void draw16bpp_mode1_half(dword addr);
50+
void draw16bpp_mode2_half(dword addr);
51+
52+
void draw24bpp_border(void);
53+
void draw24bpp_mode0(dword addr);
54+
void draw24bpp_mode1(dword addr);
55+
void draw24bpp_mode2(dword addr);
56+
void draw24bpp_border_double(void);
57+
void draw24bpp_mode0_double(dword addr);
58+
void draw24bpp_mode1_double(dword addr);
59+
void draw24bpp_mode2_double(dword addr);
60+
void draw24bpp_border_half(void);
61+
void draw24bpp_mode0_half(dword addr);
62+
void draw24bpp_mode1_half(dword addr);
63+
void draw24bpp_mode2_half(dword addr);
64+
65+
void draw32bpp_border(void);
66+
void draw32bpp_mode0(dword addr);
67+
void draw32bpp_mode1(dword addr);
68+
void draw32bpp_mode2(dword addr);
69+
void draw32bpp_border_double(void);
70+
void draw32bpp_mode0_double(dword addr);
71+
void draw32bpp_mode1_double(dword addr);
72+
void draw32bpp_mode2_double(dword addr);
73+
void draw32bpp_border_half(void);
74+
void draw32bpp_mode0_half(dword addr);
75+
void draw32bpp_mode1_half(dword addr);
76+
void draw32bpp_mode2_half(dword addr);
77+
78+
#endif

0 commit comments

Comments
 (0)