Common Source Code Project for Qt (a.k.a for FM-7).
Revisão | 3bc4bc0f2bb64107219794dca6b21b7c8150cf54 (tree) |
---|---|
Hora | 2020-03-25 23:03:55 |
Autor | K.Ohta <whatisthis.sowhat@gmai...> |
Commiter | K.Ohta |
[VM][FMTOWNS][CRTC] Add registers dump feature.
[VM][FMTOWNS][SPRITE] Delete unused cache feature.
@@ -13,6 +13,7 @@ | ||
13 | 13 | #include "towns_vram.h" |
14 | 14 | #include "towns_sprite.h" |
15 | 15 | #include "fontroms.h" |
16 | +#include "../debugger.h" | |
16 | 17 | |
17 | 18 | namespace FMTOWNS { |
18 | 19 | enum { |
@@ -87,7 +88,7 @@ void TOWNS_CRTC::release() | ||
87 | 88 | void TOWNS_CRTC::reset() |
88 | 89 | { |
89 | 90 | // initialize |
90 | - display_enabled = false; | |
91 | + display_enabled = true; | |
91 | 92 | vblank = true; |
92 | 93 | vsync = hsync = false; |
93 | 94 |
@@ -1873,6 +1874,73 @@ void TOWNS_CRTC::event_frame() | ||
1873 | 1874 | } |
1874 | 1875 | } |
1875 | 1876 | |
1877 | +bool TOWNS_CRTC::write_debug_reg(const _TCHAR *reg, uint32_t data) | |
1878 | +{ | |
1879 | + return false; | |
1880 | +} | |
1881 | + | |
1882 | +bool TOWNS_CRTC::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len) | |
1883 | +{ | |
1884 | + if(buffer == NULL) return false; | |
1885 | + | |
1886 | + _TCHAR paramstr[2048] = {0}; | |
1887 | + my_stprintf_s(paramstr, sizeof(paramstr) / sizeof(_TCHAR), | |
1888 | + _T("\n") | |
1889 | + _T("DISPLAY: %s / VCOUNT=%d / FRAMES PER SEC=%6g / FRAME uS=%6g / CLOCK=%6gMHz\n") | |
1890 | + _T("LINES PER FRAME=%d / PIXELS PER LINE=%d / MAX LINE=%d\n") | |
1891 | + _T("EET uS=%6g /") | |
1892 | + _T("VST1 uS=%6g / VST2 uS=%6g\n") | |
1893 | + _T("HORIZ uS=%6g / POSI uS=%6g / NEGA uS=%6g\n") | |
1894 | + _T("VERT START uS [0]=%6g [1]=%6g / END uS [0]=%6g [1]=%6g\n") | |
1895 | + _T("HORIZ START uS [0]=%6g [1]=%6g / END uS [0]=%6g [1]=%6g\n\n") | |
1896 | + , (display_enabled) ? _T("ON ") : _T("OFF"), vert_line_count | |
1897 | + , frames_per_sec, frame_us, 1.0 / crtc_clock | |
1898 | + , lines_per_frame, pixels_per_line, max_lines | |
1899 | + , eet_us | |
1900 | + , vst1_us, vst2_us | |
1901 | + , horiz_us, horiz_width_posi_us, horiz_width_nega_us | |
1902 | + , vert_start_us[0], vert_start_us[1], vert_end_us[0], vert_end_us[1] | |
1903 | + , horiz_start_us[0], horiz_start_us[1], horiz_end_us[0], horiz_end_us[1] | |
1904 | + ); | |
1905 | + | |
1906 | + _TCHAR regstr[1024] = {0}; | |
1907 | + my_stprintf_s(regstr, sizeof(regstr) / sizeof(_TCHAR), | |
1908 | + _T("REGS: +0 +1 +2 +3 +4 +5 +6 +7\n") | |
1909 | + _T("------------------------------------------------------\n") | |
1910 | + ); | |
1911 | + for(int r = 0; r < 32; r += 8) { | |
1912 | + _TCHAR tmps[32] = {0}; | |
1913 | + my_stprintf_s(tmps, sizeof(tmps) / sizeof(_TCHAR), "+%02d: ", r); | |
1914 | + my_tcscat_s(regstr, sizeof(regstr) / sizeof(_TCHAR), tmps); | |
1915 | + for(int q = 0; q < 8; q++) { | |
1916 | + my_stprintf_s(tmps, sizeof(tmps) / sizeof(_TCHAR), _T("%04X "), regs[r + q]); | |
1917 | + my_tcscat_s(regstr, sizeof(regstr) / sizeof(_TCHAR), tmps); | |
1918 | + } | |
1919 | + my_tcscat_s(regstr, sizeof(regstr) / sizeof(_TCHAR), _T("\n")); | |
1920 | + } | |
1921 | + my_stprintf_s(buffer, buffer_len, | |
1922 | + _T("%s") | |
1923 | + _T("SPRITE ENABLED=%s / SPRITE DISP=%d \n") | |
1924 | + _T("ZOOM[0] V=%d H=%d VCOUNT=%d / ZOOM[1] V=%d H=%d VCOUNT=%d\n") | |
1925 | + _T("VSYNC=%s / VBLANK=%s / VDISP=%s / FRAME IN[0]=%s / [1]=%s\n") | |
1926 | + _T("HSYNC=%s / HDISP[0]=%s / [1]=%s\n\n") | |
1927 | + _T("%s") | |
1928 | + , paramstr | |
1929 | +// , line_count[0], line_count[1] | |
1930 | + , (sprite_enabled) ? _T("YES") : _T("NO"), sprite_disp_page | |
1931 | + , zoom_factor_vert[0], zoom_factor_horiz[0], zoom_count_vert[0] | |
1932 | + , zoom_factor_vert[1], zoom_factor_horiz[1], zoom_count_vert[1] | |
1933 | + , (vsync) ? _T("YES") : _T("NO "), (vblank) ? _T("YES") : _T("NO ") | |
1934 | + , (vdisp) ? _T("YES") : _T("NO ") | |
1935 | + , (frame_in[0]) ? _T("YES") : _T("NO ") | |
1936 | + , (frame_in[1]) ? _T("YES") : _T("NO ") | |
1937 | + , (hsync) ? _T("YES") : _T("NO ") | |
1938 | + , (hdisp[0]) ? _T("YES") : _T("NO ") | |
1939 | + , (hdisp[1]) ? _T("YES") : _T("NO ") | |
1940 | + , regstr | |
1941 | + ); | |
1942 | + return true; | |
1943 | +} | |
1876 | 1944 | void TOWNS_CRTC::event_callback(int event_id, int err) |
1877 | 1945 | { |
1878 | 1946 | /* |
@@ -100,6 +100,8 @@ | ||
100 | 100 | #define SIG_TOWNS_CRTC_SPRITE_DISP 10 |
101 | 101 | #define SIG_TOWNS_CRTC_SPRITE_USING 11 |
102 | 102 | #define SIG_TOWNS_CRTC_COMPATIBLE_MMIO 12 |
103 | + | |
104 | +class DEBUGGER; | |
103 | 105 | namespace FMTOWNS { |
104 | 106 | |
105 | 107 | enum { |
@@ -181,7 +183,8 @@ protected: | ||
181 | 183 | TOWNS_VRAM* d_vram; |
182 | 184 | TOWNS_SPRITE* d_sprite; |
183 | 185 | DEVICE* d_font; |
184 | - | |
186 | + DEBUGGER* d_debugger; | |
187 | + | |
185 | 188 | uint16_t machine_id; |
186 | 189 | uint8_t cpu_id; |
187 | 190 | bool is_compatible; |
@@ -388,7 +391,22 @@ public: | ||
388 | 391 | |
389 | 392 | void event_callback(int event_id, int err); |
390 | 393 | bool process_state(FILEIO* state_fio, bool loading); |
391 | - | |
394 | + | |
395 | + bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len); | |
396 | + bool write_debug_reg(const _TCHAR *reg, uint32_t data); | |
397 | + | |
398 | + bool is_debugger_available() | |
399 | + { | |
400 | + return true; | |
401 | + } | |
402 | + void *get_debugger() | |
403 | + { | |
404 | + return d_debugger; | |
405 | + } | |
406 | + uint64_t get_debug_data_addr_space() | |
407 | + { | |
408 | + return 0x0; | |
409 | + } | |
392 | 410 | // unique function |
393 | 411 | linebuffer_t* __FASTCALL get_line_buffer(int page, int line) |
394 | 412 | { |
@@ -411,6 +429,10 @@ public: | ||
411 | 429 | { |
412 | 430 | d_font = dev; |
413 | 431 | } |
432 | + void set_context_debugger(DEBUGGER* dev) | |
433 | + { | |
434 | + d_debugger = dev; | |
435 | + } | |
414 | 436 | void set_machine_id(uint16_t val) |
415 | 437 | { |
416 | 438 | machine_id = val & 0xfff8; |
@@ -59,258 +59,6 @@ void TOWNS_SPRITE::reset() | ||
59 | 59 | memset(reg_data, 0x00, sizeof(reg_data)); // OK? |
60 | 60 | // ankcg_enabled = false; |
61 | 61 | } |
62 | -#if 0 | |
63 | -void TOWNS_SPRITE::clear_cache(int num) | |
64 | -{ | |
65 | - if(num >= TOWNS_SPRITE_CACHE_NUM) return; | |
66 | - if(num < 0) return; | |
67 | - memset(&(cache_index[num]), 0x00, sizeof(sprite_cache_t)); | |
68 | - memset(&(cache_pixels[num][0]) , 0x00, sizeof(uint16_t) * 16 * 16); | |
69 | - memset(&(cache_masks[num][0]) , 0x00, sizeof(uint16_t) * 16 * 16); | |
70 | - cache_index[num].is_use = false; | |
71 | - cache_index[num].pixels = &(cache_pixels[num][0]); | |
72 | - cache_index[num].masks = &(cache_masks[num][0]); | |
73 | -} | |
74 | - | |
75 | -bool TOWNS_SPRITE::check_cache(int num, sprite_cache_t** p) | |
76 | -{ | |
77 | - sprite_cache_t* q; | |
78 | - sprite_table_t* t; | |
79 | - if(p != NULL) *p = NULL; | |
80 | - | |
81 | - t = &(sprite_table[num]); | |
82 | - if(use_cache) { | |
83 | - for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) { | |
84 | - q = &(cache_index[i]); | |
85 | - if(!(q->is_use)) continue; | |
86 | - if(q->attribute == t->attribute) { | |
87 | - if(q->is_32768 == t->is_32768) { | |
88 | - if((q->is_halfy == t->is_halfy) && (q->is_halfx == t->is_halfx)) { | |
89 | - if(p != NULL) *p = q; | |
90 | - return true; | |
91 | - } | |
92 | - } | |
93 | - } | |
94 | - } | |
95 | - } | |
96 | - return false; | |
97 | -} | |
98 | - | |
99 | -void TOWNS_SPRITE::render_sprite(int num, int x, int y, uint16_t attr, uint16_t color) | |
100 | -{ | |
101 | - uint16_t sprite_limit = reg_index & 0x3ff; | |
102 | - if(sprite_limit == 0) sprite_limit = 1024; | |
103 | - if(num < 0) return; | |
104 | - if(num >= sprite_limit) return; | |
105 | - if(num >= 1024) return; | |
106 | - if(stride <= 0) return; | |
107 | - if(stride > 512) return; | |
108 | - if(!(sprite_table[num].is_disp)) return; | |
109 | - | |
110 | - sprite_cache_t *cacheptr; | |
111 | - bool c_stat = false; | |
112 | - c_stat = check_cache(num, &cacheptr); | |
113 | - if((c_stat) && (cacheptr != NULL)) { | |
114 | - if((cacheptr->pixels != NULL) && (cacheptr->masks != NULL)) { | |
115 | - render_zoomed_pixels(x, y, cacheptr->pixels, cacheptr->masks, cacheptr->is_halfx, cacheptr->is_halfy, dst_pixel, dst_mask); | |
116 | - return; | |
117 | - } | |
118 | - } | |
119 | - // Cache Not hit | |
120 | - // ToDo: Implement Link counter. | |
121 | - int target_num = -1; | |
122 | - for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) { | |
123 | - if(!(cache_index[i].is_use)) { | |
124 | - target_num = i; | |
125 | - break; | |
126 | - } | |
127 | - } | |
128 | - if((target_num < 0) || (target_num >= TOWNS_SPRITE_CACHE_NUM)) { | |
129 | - // Force erace a cache. | |
130 | - target_num = (last_put_cache_num + 1) % TOWNS_SPRITE_CACHE_NUM; | |
131 | - } | |
132 | - last_put_cache_num = target_num; | |
133 | - | |
134 | - cacheptr = &(cache_index[target_num]); | |
135 | - | |
136 | - memset(cacheptr, 0x00, sizeof(sprite_cache_t)); | |
137 | - cacheptr->is_use = true; | |
138 | - cacheptr->attribute = sprite_table[num].attribute; | |
139 | - cacheptr->is_32768 = sprite_table[num].is_32768; | |
140 | - cacheptr->is_halfx = sprite_table[num].is_halfx; | |
141 | - cacheptr->is_halfy = sprite_table[num].is_halfy; | |
142 | - cacheptr->pixels = (uint16_t*)(&(cache_pixels[target_num][0])); | |
143 | - cacheptr->masks = (uint16_t*)(&(cache_masks[target_num][0])); | |
144 | - cacheptr->color = sprite_table[num].color; | |
145 | - cacheptr->num = sprite_table[num].num; | |
146 | - cacheptr->rotate_type = sprite_table[num].rotate_type; | |
147 | - | |
148 | - if(!(cacheptr->is_32768)) { | |
149 | - // ToDo | |
150 | - color_cached[(cacheptr->color) & 0xff] = true; | |
151 | - } | |
152 | - pattern_cached[sprite_table[num].num] = true; // OK? | |
153 | - | |
154 | - switch((sprite_table[num].rotate) & 7) { | |
155 | - case 0: | |
156 | - rot_type = ROT_FMTOWNS_SPRITE_0; | |
157 | - is_mirror = false; | |
158 | - break; | |
159 | - case 1: | |
160 | - rot_type = ROT_FMTOWNS_SPRITE_180; | |
161 | - is_mirror = true; | |
162 | - break; | |
163 | - case 2: | |
164 | - rot_type = ROT_FMTOWNS_SPRITE_180; | |
165 | - is_mirror = false; | |
166 | - break; | |
167 | - case 3: | |
168 | - rot_type = ROT_FMTOWNS_SPRITE_0; | |
169 | - is_mirror = true; | |
170 | - break; | |
171 | - case 4: | |
172 | - rot_type = ROT_FMTOWNS_SPRITE_270; | |
173 | - is_mirror = true; | |
174 | - break; | |
175 | - case 5: | |
176 | - rot_type = ROT_FMTOWNS_SPRITE_90; | |
177 | - is_mirror = false; | |
178 | - break; | |
179 | - case 6: | |
180 | - rotate = false; | |
181 | - rot_type = ROT_FMTOWNS_SPRITE_270; | |
182 | - is_mirror = false; | |
183 | - break; | |
184 | - case 7: | |
185 | - rot_type = ROT_FMTOWNS_SPRITE_90; | |
186 | - is_mirror = true; | |
187 | - break; | |
188 | - } | |
189 | - uint32_t index_num = cacheptr->attribute & 0x3ff; | |
190 | - if(index_num < 128) return; | |
191 | - | |
192 | - uint8_t* src = &(pattern_ram[index_num << 7]); | |
193 | - bool is_32768 = cacheptr->is_32768; | |
194 | - bool is_halfx = cacheptr->is_halfx; | |
195 | - bool is_halfy = cacheptr->is_halfy; | |
196 | - | |
197 | - if((cacheptr->pixels != NULL) || (cacheptr->masks != NULL)) return; | |
198 | - switch(rot_type) { | |
199 | - case ROT_FMTOWNS_SPRITE_00: | |
200 | - rot_data_0(src, is_mirror, cacheptr->pixels, cacheptr->masks, is_32768, is_halfx, is_halfy); | |
201 | - break; | |
202 | - case ROT_FMTOWNS_SPRITE_90: | |
203 | - rot_data_0(src, is_mirror, cacheptr->pixels, cacheptr->masks, is_32768, is_halfx, is_halfy); | |
204 | - break; | |
205 | - case ROT_FMTOWNS_SPRITE_180: | |
206 | - rot_data_0(src, is_mirror, cacheptr->pixels, cacheptr->masks, is_32768, is_halfx, is_halfy); | |
207 | - break; | |
208 | - case ROT_FMTOWNS_SPRITE_270: | |
209 | - rot_data_0(src, is_mirror, cacheptr->pixels, cacheptr->masks, is_32768, is_halfx, is_halfy); | |
210 | - break; | |
211 | - } | |
212 | - // ToDo: wrap round.This is still bogus implement. | |
213 | - // ToDo: Separate writing buffer and integrate cache. | |
214 | - // copy cache to buffer | |
215 | - render_zoomed_pixels(x, y, cacheptr->pixels, cacheptr->masks, cacheptr->is_halfx, cacheptr->is_halfy, dst_pixel, dst_mask); | |
216 | - return; | |
217 | -} | |
218 | - | |
219 | -void TOWNS_SPRITE::render_zoomed_pixels(int x, int y, int uint16_t* pixels, uint16_t* masks, bool is_halfx, bool is_halfy, uint16_t* dst_pixel, uint16_t* dst_mask) | |
220 | -{ | |
221 | - static const int stride = 256; | |
222 | - uint16_t* pp = cache_index[target_num].pixels; | |
223 | - uint16_t* pq = cache_index[target_num].masks; | |
224 | - uint16_t* pd; | |
225 | - uint16_t* pm; | |
226 | - int w, h; | |
227 | - int beginx, beginy; | |
228 | - bool is_wrapx = false; | |
229 | - bool is_wrapy = false; | |
230 | - int offset; | |
231 | - int ww, hh; | |
232 | - w = 16; | |
233 | - h = 16; | |
234 | - beginx = 0; | |
235 | - beginy = 0; | |
236 | - if(is_halfx) { | |
237 | - w = 8; | |
238 | - } | |
239 | - if(is_halfy) { | |
240 | - h = 8; | |
241 | - } | |
242 | - if((x < 0) || (y < 0)) return; | |
243 | - if((x > 511) || (y > 511)) return; | |
244 | - if((x >= (512 - w)) && (x < 512)) { | |
245 | - beginx = x - (512 - 16); | |
246 | - ww = w - beginx; | |
247 | - is_wrapx = true; | |
248 | - } else if((x >= (256 - w)) && (x < 256)) { | |
249 | - beginx = 0; | |
250 | - ww = 256 - x; | |
251 | - } else { | |
252 | - ww = w; | |
253 | - } | |
254 | - if((y >= (512 - h)) && (y < 512)) { | |
255 | - beginy = y - (512 - 16); | |
256 | - hh = h - beginy; | |
257 | - is_wrapy = true; | |
258 | - } else if((y >= 256 - h) && (y < 256)) { | |
259 | - beginy = 0; | |
260 | - hh = 256 - y; | |
261 | - } else { | |
262 | - hh = h; | |
263 | - } | |
264 | - if(!(is_wrapx) && !(is_wrapy)) { | |
265 | - if((hh <= 0) || (ww <= 0)) return; | |
266 | - } | |
267 | - if(is_wrapx) { // Check Y | |
268 | - if(y >= 256) return; | |
269 | - } | |
270 | - if(is_wrapy) { // Check Y | |
271 | - if(x >= 256) return; | |
272 | - } | |
273 | - if(is_wrapy) { | |
274 | - offset = 0 + (is_wrapx) ? 0 : x; | |
275 | - } else if(is_wrapx) { | |
276 | - offset = (y * stride) + 0; | |
277 | - } else { | |
278 | - if((x >= 256) || (y >= 256)) return; | |
279 | - offset = (y * stride) + x; | |
280 | - } | |
281 | - // ToDo: Add offset registers. | |
282 | - | |
283 | - uint16_t cacheline[16]; | |
284 | - uint16_t mcacheline[16]; | |
285 | - uint16_t pcacheline[16]; | |
286 | - uint16_t mcacheline2[16]; | |
287 | - int cache_stride = (is_halfx) ? 3 : 4; | |
288 | - | |
289 | - pd = &(dst_pixels[offset]); | |
290 | - pm = &(dst_mask[offset]); | |
291 | - for(int y = beginy; y < (hh + beginy); y++) { | |
292 | - uint16_t* rp = &(pp[(y << cache_stride) + beginx]); | |
293 | - uint16_t* rq = &(pq[(y << cache_stride) + beginx]); | |
294 | -__DECL_VECTORIZED_LOOP | |
295 | - for(int x = 0; x < ww; x++) { | |
296 | - cacheline[x] = rp[x]; | |
297 | - mcacheline[x] = rq[x]; | |
298 | - pcacheline[x] = pd[x]; | |
299 | - } | |
300 | -__DECL_VECTORIZED_LOOP | |
301 | - for(int x = 0; x < ww; x++) { | |
302 | - pm[x] = pm[x] | mcacheline[x]; // Fill mask what pixel is drawn. | |
303 | - | |
304 | - cacheline[x] = cacheline[x] & mcacheline[x]; | |
305 | - mcacheline[x] = ~mcacheline[x]; // Invert mask | |
306 | - pcacheline[x] = pcacheline[x] & mcacheline[x]; | |
307 | - pd[x] = cacheline[x] | pcacheline[x]; | |
308 | - } | |
309 | - pd = pd + stride; | |
310 | - } | |
311 | -} | |
312 | - | |
313 | -#else | |
314 | 62 | // Still don't use cache. |
315 | 63 | void TOWNS_SPRITE::render_sprite(int num, int x, int y, uint16_t attr, uint16_t color) |
316 | 64 | { |
@@ -619,8 +367,7 @@ __DECL_VECTORIZED_LOOP | ||
619 | 367 | now_transferring = false; |
620 | 368 | |
621 | 369 | } |
622 | - | |
623 | -#endif | |
370 | + | |
624 | 371 | // Q: Does split rendering per vline? |
625 | 372 | void TOWNS_SPRITE::render_full() |
626 | 373 | { |