• R/O
  • HTTP
  • SSH
  • HTTPS

common_source_project-fm7: Commit

Common Source Code Project for Qt (a.k.a for FM-7).


Commit MetaInfo

Revision25e837f6934b4de94e301e8259348716b5eb91ab (tree)
Time2019-01-12 03:43:35
AuthorK.Ohta <whatisthis.sowhat@gmai...>
CommiterK.Ohta

Log Message

[VM][FMTOWNS][CRTC] Implementing CRTC.
[VM][FMTOWNS] Will set wait-parameter to single, towns_memory.cpp.

Change Summary

Incremental Difference

--- /dev/null
+++ b/source/src/vm/fmtowns/fontrom_20pix.cpp
@@ -0,0 +1,34 @@
1+/*
2+ FUJITSU FM Towns Emulator 'eFMTowns'
3+
4+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
5+ Date : 2019.01.11 -
6+
7+ [20pixels fonts]
8+*/
9+
10+#include "../../fileio.h"
11+#include "./fontrom_20pix.h"
12+
13+namespace FMTOWNS {
14+
15+void FONT_ROM_20PIX::initialize()
16+{
17+ FILEIO* fio = new FILEIO();
18+ memset(font_kanji20, sizeof(font_kanji20), 0xff);
19+ if(fio->Fopen(create_local_path(_T("FMT_F20.ROM")), FILEIO_READ_BINARY)) { // FONT
20+ fio->Fread(font_kanji20, sizeof(font_kanji20), 1);
21+ fio->Fclose();
22+ }
23+ delete fio;
24+}
25+
26+uint32_t FONT_ROM_20PIX::read_data8(uint32_t addr)
27+{
28+ if((addr >= 0xc2180000) && (addr < 0xc2200000)) {
29+ return (uint32_t)(font_kanji20[addr & 0x7ffff]);
30+ }
31+ return 0xff;
32+}
33+
34+}
--- /dev/null
+++ b/source/src/vm/fmtowns/fontrom_20pix.h
@@ -0,0 +1,32 @@
1+/*
2+ FUJITSU FM Towns Emulator 'eFMTowns'
3+
4+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
5+ Date : 2019.01.09 -
6+
7+ [fonts]
8+*/
9+
10+#pragma once
11+
12+#include "../device.h"
13+
14+namespace FMTOWNS {
15+
16+class FONT_ROM_20PIX : public DEVICE
17+{
18+protected:
19+ uint8_t font_kanji20[0x40000];
20+public:
21+ FONT_ROM_20PIX(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
22+ {
23+ set_device_name("Font Roms(20pix)");
24+ }
25+ ~FONT_ROM_20PIX() {}
26+
27+ void initialize();
28+ uint32_t read_data8(uint32_t addr);
29+};
30+
31+}
32+
--- a/source/src/vm/fmtowns/fontroms.cpp
+++ b/source/src/vm/fmtowns/fontroms.cpp
@@ -7,7 +7,6 @@
77 [fonts]
88 */
99
10-#inclide "../towns_common.h"
1110 #include "../../fileio.h"
1211 #include "./fontroms.h"
1312
@@ -15,22 +14,12 @@ namespace FMTOWNS {
1514
1615 void FONT_ROMS::initialize()
1716 {
18- wait_val = 3;
1917 memset(font_kanji16, sizeof(font_kanji16), 0xff);
2018 FILEIO* fio = new FILEIO();
21-
2219 if(fio->Fopen(create_local_path(_T("FMT_FNT.ROM")), FILEIO_READ_BINARY)) { // FONT
2320 fio->Fread(font_kanji16, sizeof(font_kanji16), 1);
2421 fio->Fclose();
2522 }
26-
27-#if defined(HAVE_20PIXS_FONT)
28- memset(font_kanji20, sizeof(font_kanji20), 0xff);
29- if(fio->Fopen(create_local_path(_T("FMT_F20.ROM")), FILEIO_READ_BINARY)) { // FONT
30- fio->Fread(font_kanji20, sizeof(font_kanji20), 1);
31- fio->Fclose();
32- }
33-#endif
3423
3524 delete fio;
3625 }
@@ -39,12 +28,6 @@ uint32_t FONT_ROMS::read_data8(uint32_t addr)
3928 {
4029 if((addr >= 0xc2100000) && (addr < 0xc2140000)) {
4130 return (uint32_t)(font_kanji16[addr & 0x3ffff]);
42- } else if((addr >= 0xc2180000) && (addr < 0xc2200000)) {
43-#if defined(HAVE_20PIXS_FONT)
44- return (uint32_t)(font_kanji20[addr & 0x7ffff]);
45-#else
46- return 0xff;
47-#endif
4831 } else if((addr >= 0x000ca000) && (addr < 0x000ca800)) {
4932 return (uint32_t)(font_kanji16[0x1e800 + (addr & 0x7ff)]);
5033 } else if((addr >= 0x000cb000) && (addr < 0x000cc000)) {
@@ -53,37 +36,4 @@ uint32_t FONT_ROMS::read_data8(uint32_t addr)
5336 return 0xff;
5437 }
5538
56-uint32_t FONT_ROMS::read_data8w(uint32_t addr, int* wait)
57-{
58- if(wait != NULL) *wait = wait_val;
59- return read_data8(addr);
60-}
61-
62-void FONT_ROMS::write_data8w(uint32_t addr, uint32_t data, int* wait)
63-{
64- if(wait != NULL) *wait = wait_val;
65-}
66-
67-void FONT_ROMS::write_signal(int ch, uint32_t data, uint32_t mask)
68-{
69- if(ch == SIG_FMTOWNS_SET_MEMWAIT) {
70- wait_val = (int)data;
71- }
72-}
73-
74-#define STATE_VERSION 1
75-
76-bool FONT_ROMS::process_state(FILEIO* state_fio, bool loading)
77-{
78- if(!state_fio->StateCheckUint32(STATE_VERSION)) {
79- return false;
80- }
81- if(!state_fio->StateCheckInt32(this_device_id)) {
82- return false;
83- }
84- state_fio->StateValue(wait_val);
85-
86- return true;
87-}
88-
8939 }
--- a/source/src/vm/fmtowns/fontroms.h
+++ b/source/src/vm/fmtowns/fontroms.h
@@ -17,11 +17,7 @@ namespace FMTOWNS {
1717 class FONT_ROMS : public DEVICE
1818 {
1919 protected:
20- int wait_val;
2120 uint8_t font_kanji16[0x40000];
22-#if defined(HAVE_20PIXS_FONT)
23- uint8_t font_kanji20[0x80000];
24-#endif
2521 public:
2622 FONT_ROMS(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
2723 {
@@ -30,12 +26,7 @@ public:
3026 ~FONT_ROMS() {}
3127
3228 void initialize();
33-
3429 uint32_t read_data8(uint32_t addr);
35- uint32_t read_data8w(uint32_t addr, int* wait);
36- void write_data8w(uint32_t addr, uint32_t data, int* wait);
37- void write_signal(int ch, uint32_t data, uint32_t mask);
38- bool process_state(FILEIO* state_fio, bool loading);
3930 };
4031
4132 }
--- a/source/src/vm/fmtowns/msdosrom.cpp
+++ b/source/src/vm/fmtowns/msdosrom.cpp
@@ -21,8 +21,6 @@ void MSDOSROM::initialize()
2121 fio->Fclose();
2222 }
2323 delete fio;
24-
25- wait_val = 3;
2624 }
2725
2826 uint32_t MSDOSROM::read_data8(uint32_t addr)
@@ -34,47 +32,5 @@ uint32_t MSDOSROM::read_data8(uint32_t addr)
3432 return (uint32_t)d;
3533 }
3634
37-uint32_t MSDOSROM::read_data8w(uint32_t addr, int* wait)
38-{
39- if(wait != NULL) *wait = wait_val;
40- return read_data8(addr);
41-}
42-void MSDOSROM::write_data8w(uint32_t addr, uint32_t data, int* wait)
43-{
44- if(wait != NULL) *wait = wait_val;
45-}
46-
47-void MSDOSROM::write_signal(int ch, uint32_t data, uint32_t mask)
48-{
49- switch(ch) {
50- case SIG_FMTOWNS_SET_MEMWAIT:
51- wait_val = (int)data;
52- break;
53- }
54-}
55-
56-uint32_t MSDOSROM::read_signal(int ch)
57-{
58- switch(ch) {
59- case SIG_FMTOWNS_SET_MEMWAIT:
60- return (uint32_t)wait_val;
61- break;
62- }
63- return 0;
64-}
65-
66-#define STATE_VERSION 1
67-
68-bool DICTIONARY::process_state(FILEIO* state_fio, bool loading)
69-{
70- if(!state_fio->StateCheckUint32(STATE_VERSION)) {
71- return false;
72- }
73- if(!state_fio->StateCheckInt32(this_device_id)) {
74- return false;
75- }
76- state_fio->StateValue(wait_val);
77- return true;
78-}
7935
8036 }
--- a/source/src/vm/fmtowns/msdosrom.h
+++ b/source/src/vm/fmtowns/msdosrom.h
@@ -23,7 +23,7 @@ public:
2323 ~MSDOSROM() {}
2424
2525 void initialize();
26-
26+ uint32_t read_data8(uint32_t addr);
2727 };
2828
2929 }
--- a/source/src/vm/fmtowns/towns_crtc.cpp
+++ b/source/src/vm/fmtowns/towns_crtc.cpp
@@ -12,14 +12,18 @@
1212
1313 namespace FMTOWNS {
1414 enum {
15- EVENT_CRTC_VSTART = 0,
15+ EVENT_CRTC_VSTART = 1,
1616 EVENT_CRTC_VST1 = 2,
17- EVENT_CRTC_VST2 = 4,
18- EVENT_CRTC_VDS = 6,
19- EVENT_CRTC_VDE = 8,
20- EVENT_CRTC_HSTART = 10,
21- EVENT_CRTC_HEND = 12,
22- EVENT_CRTC_HSW = 14,
17+ EVENT_CRTC_VST2 = 3,
18+ EVENT_CRTC_HSTART = 4,
19+ EVENT_CRTC_HEND = 5,
20+ EVENT_CRTC_HSW = 6,
21+ EVENT_CRTC_EET = 7,
22+ EVENT_CRTC_VDS = 32,
23+ EVENT_CRTC_VDE = 34,
24+ EVENT_CRTC_HDS = 36,
25+ EVENT_CRTC_HDE = 38,
26+
2327 };
2428
2529
@@ -112,137 +116,292 @@ void TOWNS_CRTC::set_crtc_clock(uint16_t val)
112116 {
113117 scsel = (val & 0x0c) >> 2;
114118 clksel = val & 0x03;
115- const double clocks[] = {
119+ static const double clocks[] = {
116120 28.6363e6, 24.5454e6, 25.175e6, 21.0525e6
117121 };
118122 if(crtc_clock[clksel] != crtc_clock) {
119123 crtc_clock = crtc_clock[clksel];
120- force_recalc_crtc_param(-1);
124+ force_recalc_crtc_param();
121125 }
122126 }
123127
124-void TOWNS_CRTC::set_crtc_hsw1(void)
125-{
126- int val = (int)(regs[ch + TOWNS_CRTC_REG_HSW1] & 0x0fff);
127- horiz_width_posi_us = horiz_us * (double)val;
128- // Update
129-}
130-void TOWNS_CRTC::set_crtc_hsw2(void)
128+void TOWNS_CRTC::force_recalc_crtc_param(void)
131129 {
132- int val = (int)(regs[TOWNS_CRTC_REG_HSW2] & 0x0fff);
133- horiz_width_nega_us = horiz_us * (double)val;
134- // Update
135-}
130+ horiz_width_posi_us = crtc_clock * ((double)(regs[0] & 0x00fe)); // HSW1
131+ horiz_width_nega_us = crtc_clock * ((double)(regs[1] & 0x00fe)); // HSW2
132+ horiz_us = crtc_clock * ((double)((regs[4] & 0x07fe) + 1)); // HST
133+ vsync_pre_us = ((double)(regs[5] & 0x1f)) * horiz_us; // VST1
136134
137-void TOWNS_CRTC::set_crtc_hst(void)
138-{
139- int val = (int)(regs[TOWNS_CRTC_REG_HST] & 0x07ff) | 1;
140- next_horiz_us = (double)(val + 1) * 1.0 / crtc_clock;
141- // Update
135+ double horiz_ref = horiz_us / 2.0;
136+
137+ vst2_us = ((double)(regs[6] & 0x1f)) * horiz_ref; // VST2
138+ eet_us = ((double)(regs[7] & 0x1f)) * horiz_ref; // EET
139+ frame_us = ((double)(regs[8] & 0x07ff)) * horiz_ref; // VST
140+
141+ for(int layer = 0; layer < 2; layer++) {
142+ vert_start_us[layer] = ((double)(regs[(layer << 1) + 13] & 0x07ff)) * horiz_ref; // VDSx
143+ vert_end_us[layer] = ((double)(regs[(layer << 1) + 13 + 1] & 0x07ff)) * horiz_ref; // VDEx
144+ horiz_start_us[layer] = ((double)(regs[(layer << 1) + 9] & 0x07ff)) * crtc_clock ; // HDSx
145+ horiz_end_us[layer] = ((double)(regs[(layer << 1) + 9 + 1] & 0x07ff)) * crtc_clock ; // HDEx
146+ }
147+
142148 }
143149
144-void TOWNS_CRTC::set_crtc_vst1(void)
150+
151+void TONWS_CRTC::write_io8(uint32_t addr, uint32_t data)
145152 {
146- int val = (int)regs[TOWNS_CRTC_REG_VST1];
147- vert_sync_pre_us = ((double)val * horiz_us) / 2.0;
153+ if(addr == 0x0440) {
154+ ch = data & 0x1f;
155+ } else if(addr == 0x0442) {
156+ pair16_t rdata;
157+ rdata.w = regs[ch];
158+ rdata.l = (uint8_t)data;
159+ write_io16(addr, rdata.w);
160+ } else if(addr == 0x0443) {
161+ pair16_t rdata;
162+ rdata.w = regs[ch];
163+ rdata.h = (uint8_t)data;
164+ write_io16(addr, rdata.w);
165+ }
148166 }
149167
150-void TOWNS_CRTC::set_crtc_vst2(void)
168+void TOWNS_CRTC::write_io16(uint32_t addr, uint32_t data)
151169 {
152- int val = (int)regs[TOWNS_CRTC_REG_VST2];
153- vert_sync_end_us = ((double)val * horiz_us) / 2.0;
170+ if((addr & 0xfffe) == 0x0442) {
171+ if(ch < 32) {
172+ if((ch < 0x09) && ((ch >= 0x04) || (ch <= 0x01))) { // HSW1..VST
173+ if(regs[ch] != (uint16_t)data) {
174+ force_recalc_crtc_param();
175+ }
176+ } else if(ch < 0x11) { // HDS0..VDE1
177+ uint8_t localch = ((ch - 0x09) / 2) & 1;
178+ if(regs[ch] != (uint16_t)data) {
179+ timing_changed[localch] = true;
180+ // ToDo: Change render parameter within displaying.
181+ force_recalc_crtc_param();
182+ }
183+ }else if(ch < 0x19) { // FA0..LO1
184+ uint8_t localch = (ch - 0x11) / 4;
185+ uint8_t localreg = (ch - 0x11) & 3;
186+ if(regs[ch] != (uint16_t)data) {
187+ address_changed[localch] = true;
188+ switch(localreg) {
189+ case 0: // FAx
190+ vstart_addr[localch] = (uint32_t)(data & 0xffff);
191+ break;
192+ case 1: // HAJx
193+ hstart_words[localch] = (uint32_t)(data & 0x07ff);
194+ break;
195+ case 2: // FOx
196+ frame_offet[localch] = (uint32_t)(data & 0xffff);
197+ break;
198+ case 3: // LOx
199+ line_offet[localch] = (uint32_t)(data & 0xffff);
200+ break;
201+ }
202+ }
203+ } else { // All reg
204+ if(regs[ch] != (uint16_t)data) {
205+ switch(ch - 0x19) {
206+ case 0: // EHAJ
207+ case 1: // EVAJ
208+ // ToDo: External SYNC.
209+ break;
210+ case 2: // ZOOM
211+ {
212+ uint8_t zfv[2];
213+ uint8_t zfh[2];
214+ pair16_t pd;
215+ pd.w = (uint16_t)data;
216+ zfv[0] = ((pd.l & 0xf0) >> 4) + 1;
217+ zfh[0] = (pd.l & 0x0f) + 1;
218+ zfv[1] = ((pd.h & 0xf0) >> 4) + 1;
219+ zfh[1] = (pd.h & 0x0f) + 1;
220+ if((zfv[0] != zoom_factor_vert[0]) || (zfh[0] != zoom_factor_horiz[0])) {
221+ timing_changed[0] = true;
222+ address_changed[0] = true;
223+ if(zfv[0] != zoom_factor_vert[0]) zoom_count_vert[0] = zfv[0];
224+ }
225+ if((zfv[1] != zoom_factor_vert[1]) || (zfh[1] != zoom_factor_horiz[1])) {
226+ timing_changed[0] = true;
227+ address_changed[0] = true;
228+ if(zfv[1] != zoom_factor_vert[1]) zoom_count_vert[1] = zfv[1];
229+ }
230+ zoom_factor_vert[0] = zfv[0];
231+ zoom_factor_horiz[0] = zfh[0];
232+ zoom_factor_vert[1] = zfv[1];
233+ zoom_factor_horiz[1] = zfh[1];
234+ }
235+ break;
236+ case 3: // CR0
237+ if(regs[ch] != data) {
238+ if((data & 0x8000) == 0) {
239+ // START BIT
240+ restart_display();
241+ } else {
242+ stop_display();
243+ }
244+ if((data & 0x4000) == 0) {
245+ // ESYN BIT
246+ // EXTERNAL SYNC OFF
247+ } else {
248+ // EXTERNAL SYNC ON
249+ }
250+ impose_mode[1] = ((data & 0x0080) == 0);
251+ impose_mode[0] = ((data & 0x0040) == 0);
252+ carry_enable[1] = ((data & 0x0020) != 0);
253+ carry_enable[0] = ((data & 0x0010) != 0);
254+ uint8_t dmode[2];
255+ dmode[0] = data & 0x03;
256+ dmode[1] = (data & 0x0c) >> 2;
257+ for(int i = 0; i < 2; i++) {
258+ if(dmode[0] != display_mode[0]) {
259+ mode_changed[0] = true;
260+ notify_mode_changed(i, dmode[i]);
261+ }
262+ display_mode[i] = dmode[i];
263+ }
264+ }
265+ break;
266+ case 4: // CR1
267+ set_crtc_clock((uint16_t)data);
268+ break;
269+ case 5: // Reserved(REG#30)
270+ break;
271+ case 6: // CR2
272+ // ToDo: External trigger.
273+ break;
274+ }
275+ }
276+ }
277+ regs[ch] = (uint16_t)data;
278+ }
279+ } else if(addr == 0x0440) {
280+ ch = data & 0x1f;
281+ }
154282 }
155283
156-void TOWNS_CRTC::set_crtc_vst2(void)
284+uint16_t TOWNS_CRTC::read_reg30()
157285 {
158- int val = (int)regs[TOWNS_CRTC_REG_VST];
159- next_vert_us = ((double)val * horiz_us) / 2.0;
286+ uint16_t data = 0x00f0;
287+ data |= ((frame_in[1]) ? 0x8000 : 0);
288+ data |= ((frame_in[0]) ? 0x4000 : 0);
289+ data |= ((hdisp[1]) ? 0x2000 : 0);
290+ data |= ((hdisp[0]) ? 0x1000 : 0);
291+ //data |= ((eet) ? 0x0800 : 0);
292+ data |= ((vsync) ? 0x0400 : 0);
293+ data |= (!(hsync) ? 0x0200 : 0);
294+ //data |= ((video_in) ? 0x0100 : 0);
295+ //data |= ((half_tone) ? 0x0008 : 0);
296+ //data |= ((sync_enable) ? 0x0004 : 0);
297+ //data |= ((vcard_enable) ? 0x0002 : 0);
298+ //data |= ((sub_carry) ? 0x0001 : 0);
299+
160300 }
161301
162-void TOWNS_CRTC::write_io8(uint32_t addr, uint32_t data)
302+uint32_t TOWNS_CRTC::read_io16(uint32_t addr)
163303 {
164- if(addr & 1) {
165- if(ch < 32) {
166- if(ch < 16 && regs[ch] != data) {
167- timing_changed = true;
168- }
169- regs[ch] = data;
170- regs_written[ch] = true;
304+ addr = addr & 0xfffe;
305+ if(addr == 0x0440) {
306+ return (uint32_t)ch;
307+ } else if(addr == 0x0442) {
308+ if(ch == 30) {
309+ return (uint32_t)read_reg30();
310+ } else {
311+ return regs[ch];
171312 }
172- } else {
173- ch = data;
174313 }
314+ return 0xffff;
175315 }
176316
177317 uint32_t TOWNS_CRTC::read_io8(uint32_t addr)
178318 {
179- if(addr & 1) {
180- return (12 <= ch && ch < 18) ? regs[ch] : 0xff;
181- } else {
182- return ch;
319+ if(addr == 0x0440) {
320+ return (uint32_t)ch;
321+ } else if(addr == 0x0442) {
322+ pair16_t d;
323+ if(ch == 30) {
324+ d.w = read_reg32();
325+ } else {
326+ d.w = regs[ch];
327+ }
328+ return (uint32_t)(d.l);
329+ } else if(addr == 0x0443) {
330+ pair16_t d;
331+ if(ch == 30) {
332+ d.w = read_reg32();
333+ } else {
334+ d.w = regs[ch];
335+ }
336+ return (uint32_t)(d.h);
183337 }
338+ return 0xff;
184339 }
185340
186-
187-void TOWNS_CRTC::event_pre_frame()
341+// Note: This entry
342+void TOWNS_CRTC::event_line_per_layer(int display_line, int layer)
188343 {
189- if(timing_changed) {
190- if(regs_written[0] && regs_written[1] && regs_written[2] && regs_written[3] && regs_written[4] && regs_written[5] && regs_written[6] && regs_written[7] && regs_written[9]) {
191- int ch_height = (regs[9] & 0x1f) + 1;
192-
193- hz_total = regs[0] + 1;
194- hz_disp = regs[1];
195- hs_start = regs[2];
196- hs_end = hs_start + (regs[3] & 0x0f);
197-
198- int new_vt_total = ((regs[4] & 0x7f) + 1) * ch_height + (regs[5] & 0x1f);
199- vt_disp = (regs[6] & 0x7f) * ch_height;
200- vs_start = ((regs[7] & 0x7f) + 1) * ch_height;
201- vs_end = vs_start + ((regs[3] & 0xf0) ? (regs[3] >> 4) : 16);
202-
203- if(vt_total != new_vt_total) {
204- vt_total = new_vt_total;
205- set_lines_per_frame(vt_total);
206- }
207- timing_changed = false;
208- disp_end_clock = 0;
209-#if defined(TOWNS_CRTC_CHAR_CLOCK)
210- char_clock = 0;
211-#elif defined(TOWNS_CRTC_HORIZ_FREQ)
212- horiz_freq = 0;
213-#endif
214- }
215- }
216-#if defined(TOWNS_CRTC_CHAR_CLOCK)
217- if(char_clock != next_char_clock) {
218- char_clock = next_char_clock;
219- frames_per_sec = char_clock / (double)vt_total / (double)hz_total;
220- if(regs[8] & 1) {
221- frames_per_sec *= 2; // interlace mode
222- }
223- set_frames_per_sec(frames_per_sec);
344+ uint32_t startaddr;
345+ if(display_line < 0) return;
346+
347+ layer = layer & 1;
348+ if((one_layer_mode) && (layer != 0)) {
349+ d_vram->write_signal(SIG_TOWNS_VRAM_DONT_RENDER, (layer << 24) | ((uint32_t)display_line), 0x100fffff);
350+ return; // Not render.
224351 }
225-#elif defined(TOWNS_CRTC_HORIZ_FREQ)
226- if(horiz_freq != next_horiz_freq) {
227- horiz_freq = next_horiz_freq;
228- frames_per_sec = horiz_freq / (double)vt_total;
229- if(regs[8] & 1) {
230- frames_per_sec *= 2; // interlace mode
352+ zoom_count_vert[layer]--;
353+ if((zoom_count_vert[layer] == 0) || (display_line == 0)) {
354+ int vline = vram_line[layer];
355+
356+ startaddr = vstart_addr[layer];
357+ if(zoom_count_vert[layer] == 0) vram_line[layer]++;
358+ zoom_count_vert[layer] = zoom_factor_vert[layer];
359+
360+ uint32_t offset_words = (regs[(layer * 4) + 18] & 0x07ff) - (regs[(layer * 2) + 9] & 0x07ff); // HAJx - HDSx
361+ uint32_t offset_per_line = line_offset[layer];
362+ uint32_t draw_width = (regs[0x09 + layer * 2 + 1] & 0x07ff) - (regs[0x09 + layer * 2 + 0] & 0x07ff); // HDEx-HDSx
363+
364+ // ToDo: Interlace mode
365+ if(one_layer_mode) {
366+ offset_per_line = offset_per_line * 4 * 2; // 4Words.
367+ offset_words = offset_words * 4 * 2; // 4Words.
368+ } else {
369+ offset_per_line = offset_per_line * 2 * 2; // 2Words.
370+ offset_words = offset_words * 2 * 2; // 2Words.
231371 }
232- set_frames_per_sec(frames_per_sec);
372+
373+ startaddr = startaddr + offset_per_line * vline;
374+
375+ d_vram->write_signal(SIG_TOWNS_VRAM_SET_PARAM, layer, 0x1); // Begin modify rendering factor
376+ d_vram->write_signal(SIG_TOWNS_VRAM_PIX_COUNT, draw_width, 0xfffffff); // Pixel count
377+ d_vram->write_signal(SIG_TOWNS_VRAM_START_ADDR, startaddr, 0xffffffff); // VRAM START ADDRESS
378+ d_vram->write_signal(SIG_TOWNS_VRAM_HZOOM, zoom_factor_horiz[layer], 0x0f); // HZOOM factor
379+// d_vram->write_signal(SIG_TOWNS_VRAM_VZOOM, zoom_factor_vert[layer], 0x0f); // OFFSET WORD
380+ d_vram->write_signal(SIG_TOWNS_VRAM_OFFSET_WORDS, offset_words, 0xffffffff); // OFFSET WORD
381+ } else {
382+ d_vram->write_signal(SIG_TOWNS_VRAM_KEEP_PARAM, layer, 0x1); // Begin modify rendering factor
383+ }
384+ if(!(frame_in[layer])) {
385+ d_vram->write_signal(SIG_TOWNS_VRAM_DONT_RENDER, (layer << 24) | ((uint32_t)display_line), 0x100fffff);
386+ } else {
387+ d_vram->write_signal(SIG_TOWNS_VRAM_DO_RENDER, (layer << 24) | ((uint32_t)display_line), 0x100fffff);
388+ }
389+ if(!(carry_enable[layer])) {
390+ vram_line[layer] = vram_line[layer] & 0x00ff;
233391 }
234-#endif
392+}
393+
394+void TOWNS_CRTC::event_pre_frame()
395+{
396+ // ToDo: Resize frame buffer.
235397 }
236398
237399 void TOWNS_CRTC::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
238400 {
239401 cpu_clocks = new_clocks;
240-#if !defined(TOWNS_CRTC_CHAR_CLOCK) && !defined(TOWNS_CRTC_HORIZ_FREQ)
241402 frames_per_sec = new_frames_per_sec;
242-#endif
243-
244- // update event clocks
245- disp_end_clock = 0;
403+ max_lines = new_lines_per_frame;
404+ max_frame_usec = 1.0e6 / frames_per_sec;
246405 }
247406
248407 void TOWNS_CRTC::event_callback(int event_id, int err)
@@ -259,120 +418,137 @@ void TOWNS_CRTC::event_callback(int event_id, int err)
259418 * ZOOM (#27) : ToDo
260419 */
261420 int eid2 = (event_id / 2) * 2;
262- if(eid2 == EVENT_CRTC_VSTART) {
421+ if(event_id == EVENT_CRTC_VSTART) {
422+ d_vram->write_signal(SIG_TOWNS_VRAM_VSTART, 0x01, 0x01);
263423 line_count[0] = line_count[1] = 0;
264424 if((horiz_us != next_horiz_us) || (vert_us != next_vert_us)) {
265425 horiz_us = next_horiz_us;
266426 vert_us = next_vert_us;
267- force_recalc_crtc_param(-1);
268- if(event_id_vsync >= 0) cancel_event(this, event_id_vsync);
269- if(event_id_hsw >= 0) cancel_event(this, event_id_hsw);
270-
271- register_event(this, EVENT_CRTC_HSTART + 0, vert_sync_pre_us, false, &event_id_hsw); // HSW = HSYNC
272- register_event(this, EVENT_CRTC_VSTART + 0, vert_us, true, &event_id_vsync); // VST
273427 }
274- frame_in[0] = frame_in[1] = false;
275- line_count[0] = line_count[1] = 0;
276- line_count_mod[0] = line_count_mod[1] = 0;
277428 hsync = false;
278- hdisp = false;
279- vdisp = true;
280- vblank = true;
281- vsync = false;
429+ for(int i = 0; i < 2; i++) {
430+ hdisp[i] = false;
431+ }
282432 major_line_count = -1;
283- register_event(this, EVENT_CRTC_VST1 + 0, vert_sync_pre_us, false, &event_id_vstn); // VST1
284- register_event(this, EVENT_CRTC_VDS + 0, vert_start_us[0], false, &event_id_vstart[0]); // VDS0 : Layer1
285- register_event(this, EVENT_CRTC_VDS + 1, vert_start_us[1], false, &event_id_vstart[1]); // VDS1 : Layer2
286- } else if(eid2 == EVENT_CRTC_VST1) {
287- vsync = true;
288- if(vert_sync_end_us > 0.0) {
289- register_event(this, EVENT_CRTC_VST2 + 0, vert_sync_end_us, false, &event_id_vstn); // VST2 - VST1.
290- } else {
433+ // ToDo: EET
434+ register_event(this, EVENT_CRTC_VSTART, frame_us, false, &event_id_frame);
435+ if(vert_sync_pre_us >= 0.0) {
291436 vsync = false;
437+ register_event(this, EVENT_CRTC_VST1, vert_sync_pre_us, false, &event_id_vst1); // VST1
438+ } else {
439+ vsync = true;
292440 }
293- } else if (eid2 == EVENT_CRTC_VST2) {
441+ register_event(this, EVENT_CRTC_VST2, vst2_us, false, &event_id_vst2);
442+ for(int i = 0; i < 2; i++) {
443+ frame_in[i] = false;
444+ if(event_id_vds[i] != -1) {
445+ cancel_event(this, event_id_vds[i]);
446+ }
447+ if(event_id_vde[i] != -1) {
448+ cancel_event(this, event_id_vde[i]);
449+ }
450+ if(vert_start_us[i] > 0.0) {
451+ register_event(this, EVENT_CRTC_VDS + i, vert_start_us[i], false, &event_id_vds[i]); // VDSx
452+ } else {
453+ frame_in[i] = true;
454+ }
455+ if(vert_end_us[i] > 0.0) {
456+ register_event(this, EVENT_CRTC_VDE + i, vert_end_us[i], false, &event_id_vde[i]); // VDEx
457+ }
458+ }
459+
460+ if(event_id_hstart != -1) {
461+ cancel_event(this, event_id_hstart);
462+ event_id_hstart = -1;
463+ }
464+ if(event_id_hsw != -1) {
465+ cancel_event(this, event_id_hsw);
466+ event_id_hsw = -1;
467+ }
468+ } else if(event_id == EVENT_CRTC_VST1) { // VSYNC
469+ vsync = true;
470+ } else if (event_id == EVENT_CRTC_VST2) {
294471 vsync = false;
295- vblank = false;
296472 event_id_vstn = -1;
297473 } else if(eid2 == EVENT_CRTC_VDS) { // Display start
298474 int layer = event_id & 1;
299475 frame_in[layer] = true;
300476 // DO ofset line?
301- if(event_id_vend[layer] >= 0) cancel_event(this, event_id_vend[layer]);
302- register_event(this, EVENT_CRTC_VDE + layer, vert_start_us[0], false, &event_id_vend[layer]); // VDEx
303477 event_id_vstart[layer] = -1;
304478 } else if(eid2 == EVENT_CRTC_VDE) { // Display end
305479 int layer = event_id & 1;
306480 frame_in[layer] = false;
307- if(event_id_vstart[layer] >= 0) cancel_event(this, event_id_vstart[layer]);
308- event_id_vstart[layer] = -1;
309481 event_id_vend[layer] = -1;
310482 // DO ofset line?
311- } else if(eid2 == EVENT_CRTC_HSTART) {
483+ } else if(event_id == EVENT_CRTC_HSTART) {
312484 // Do render
313- hsync = true;
314- hdisp = false;
485+ event_id_hstart = -1;
315486 major_line_count++;
316- if(vsync) { // in VSYNC. Not Display.
317- if(event_id_hswn >= 0) cancel_event(this, event_id_hswn);
318- register_event(this, EVENT_CRTC_HSW + 0, hsw2_us, false, &event_id_hswn); // Indicate HSYNC
319- } else { // Not in VSYNC. May be displaied.
320- for(layer = 0; layer < 2; layer++) {
321- if(frame_in[layer] && (major_line_count >= 0) && (major_line_count < TOWNS_CRTC_MAX_LINES)) {
322- if((vstart_lines[layer] <= major_line_count) && (vend_lines[layer] => major_line_count)) {
323- // Proccessing zooming by ZOOM register(reg #27).
324- {
325- // If zoom is not supported by hardware, if first line : render.
326- // Not first: copy (put here?)
327- } // else {
328- if(line_changed[layer][line_count[layer]]) {
329- {
330- // Do rendering.
331- line_changed[layer][line_count[layer]] = false;
332- line_rendered[layer][line_count[layer]] = true;
333- }
334- }
335- }
336- {
337- // If zoom by hardware
338- line_count_mod[layer] += line_count_factor[layer]; // line_count_factor[n] = 2048 / VZOOM_FACTOR[01]
339- if(line_count_mod[layer] >= 2048) {
340- line_count[layer]++;
341- line_count_mod[layer] -= 2048;
342- }
343- }
487+ hdisp[0] = false;
488+ hdisp[1] = false;
489+ if(event_id_hsw != -1) {
490+ cancel_event(this, event_id_hsw);
491+ event_id_hsw = -1;
492+ }
493+ if(!vsync) {
494+ hsync = true;
495+ register_event(this, EVENT_CRTC_HSW, horiz_width_posi_us, false, &event_id_hsw); // VDEx
496+ } else {
497+ hsync = true;
498+ register_event(this, EVENT_CRTC_HSW, horiz_width_nega_us, false, &event_id_hsw); // VDEx
499+ }
500+ for(int i = 0; i < 2; i++) {
501+ if(event_id_hds[i] != -1) {
502+ cancel_event(this, event_id_hds[i]);
503+ }
504+ event_id_hds[i] = -1;
505+ if(event_id_hde[i] != -1) {
506+ cancel_event(this, event_id_hde[i]);
507+ }
508+ event_id_hde[i] = -1;
509+
510+ if(horiz_start_us[i] > 0.0) {
511+ register_event(this, EVENT_CRTC_HDS + i, horiz_start_us[i], false, &event_id_hds[i]); // HDS0
512+ } else {
513+ hdisp[i] = true;
514+ if(!vsync) {
515+ event_line_per_layer(major_line_count, layer);
344516 }
345517 }
346- if(event_id_hswn >= 0) cancel_event(this, event_id_hswn);
347- register_event(this, EVENT_CRTC_HSW + 0, hsw1_us, false, &event_id_hswn); // Indicate HSYNC
518+ if((horiz_end_us[i] > 0.0) && (horiz_end_us[i] > horiz_start_us[i])) {
519+ register_event(this, EVENT_CRTC_HDE + i, horiz_end_us[i], false, &event_id_hde[i]); // HDS0
520+ }
348521 }
349- } else if(eid2 == EVENT_CRTC_HSW) {
522+
523+ register_event(this, EVENT_CRTC_HSTART, horiz_us, false, &event_id_hstart); // HSTART
524+ } else if(event_id == EVENT_CRTC_HSW) {
525+ hsync = false;
526+ event_id_hsw = -1;
527+ } else if(eid2 == EVENT_CRTC_HDS) {
528+ int layer = event_id & 1;
529+ hdisp[layer] = true;
350530 if(!vsync) {
351- hdisp = true;
531+ event_line_per_layer(major_line_count, layer);
352532 }
353- hsync = false;
533+ if((horiz_end_us[i] <= 0.0) || (horiz_end_us[i] <= horiz_start_us[i])) {
534+ hdisp[layer] = false;
535+ }
536+ event_id_hds[layer] = -1;
537+ } else if(eid2 == EVENT_CRTC_HDE) {
538+ int layer = event_id & 1;
539+ hdisp[layer] = false;
540+ event_id_hde[layer] = -1;
354541 }
355542
356543 }
357544
358-void TOWNS_CRTC::set_display(bool val)
545+void TOWNS_CRTC::write_signal(int ch, uint32_t data, uint32_t mask)
359546 {
360- if(display != val) {
361- write_signals(&outputs_disp, val ? 0xffffffff : 0);
362- display = val;
547+ if(ch == SIG_TONWS_CRTC_SINGLE_LAYER) {
548+ one_layer_mode = ((data & mask) == 0);
363549 }
364550 }
365551
366-void TOWNS_CRTC::set_vblank(bool val)
367-{
368- if(vblank != val) {
369- write_signals(&outputs_vblank, val ? 0xffffffff : 0);
370- vblank = val;
371- }
372-}
373-
374-
375-
376552 #define STATE_VERSION 1
377553
378554 void TOWNS_CRTC::save_state(FILEIO* state_fio)
--- a/source/src/vm/fmtowns/towns_crtc.h
+++ b/source/src/vm/fmtowns/towns_crtc.h
@@ -125,6 +125,13 @@ namespace FMTOWNS {
125125 TOWNS_CRTC_REG_DUMMY, // 30
126126 TOWNS_CRTC_REG_CTRL, // 31
127127 };
128+
129+ enum {
130+ DISPMODE_NONE = 0,
131+ DISPMODE_32768_2,
132+ DISPMODE_32768_1,
133+ DISPMODE_256_OR_16,
134+ };
128135 }
129136
130137 namespace FMTOWNS {
@@ -134,13 +141,14 @@ private:
134141 // output signals
135142 outputs_t outputs_int_vsync; // Connect to int 11.
136143 uint16_t regs[32]; // I/O 0442H, 0443H
137- bool regs_written[32];
138- uint8_t reg_ch; // I/O 0440H
139- bool timing_changed;
140-
141- // Not include around video input/dizitize features yet.
142- bool line_changed[2][TOWNS_CRTC_MAX_LINES];
143-
144+ uint8_t ch; // I/O 0440H
145+ bool timing_changed[2];
146+ bool address_changed[2];
147+ bool mode_changed[2];
148+
149+ uint8_t display_mode[2];
150+ bool display_enabled;
151+
144152 double crtc_clock; //
145153 // They are not saved.Must be calculate when loading.
146154 double horiz_us, next_horiz_us; // (HST + 1) * clock
@@ -152,14 +160,18 @@ private:
152160 // End
153161
154162 double frames_per_sec;
155-
163+
164+ uint32_t vstart_addr[2]; // VSTART ADDRESS
156165 uint32_t hstart_words[2]; // HSTART ((HDS[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
157166 uint32_t hend_words[2]; // HEND ((HDE[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
158167 uint32_t vstart_lines[2]; // VSTART ((VDS[01] * clock) : Horizonal offset words (Related by VH[01]).
159168 uint32_t vend_lines[2]; // VEND ((VDE[01] * clock) : Horizonal offset words (Related by VH[01]).
160-
161- uint32_t zoom_factor_vert; // Related display resolutions of two layers and zoom factors. Multiplied by 1024.
162- uint32_t zoom_factor_horiz; // Related display resolutions of two layers and zoom factors. Multiplied by 1024.
169+ uint32_t frame_offset[2]; // FO.
170+ uint32_t vram_line[2];
171+
172+ uint8_t zoom_factor_vert[2]; // Related display resolutions of two layers and zoom factors.
173+ uint8_t zoom_factor_horiz[2]; // Related display resolutions of two layers and zoom factors.
174+ uint8_t zoom_count_vert[2];
163175
164176 uint32_t line_count[2]; // Separate per layer.
165177
--- a/source/src/vm/fmtowns/towns_dictionary.cpp
+++ b/source/src/vm/fmtowns/towns_dictionary.cpp
@@ -35,7 +35,6 @@ void DICTIONARY::initialize()
3535 }
3636 delete fio;
3737
38- wait_val = 3;
3938 dict_bank = 0;
4039 bankd0_dict = false;
4140 }
@@ -54,7 +53,6 @@ void DICTIONARY::release()
5453
5554 void DICTIONARY::reset()
5655 {
57- //wait_val = 6; // OK?
5856 dict_bank = 0;
5957 bankd0_dict = false;
6058
@@ -140,42 +138,6 @@ void DICTIONARY::write_data32(uint32_t addr, uint32_t data)
140138 write_data8(addr + 3, n.h3);
141139 }
142140
143-uint32_t DICTIONARY::read_data8w(uint32_t addr, int *wait)
144-{
145- if(wait != NULL) *wait = wait_val;
146- return read_data8(addr, data);
147-}
148-
149-uint32_t DICTIONARY::read_data16w(uint32_t addr, int *wait)
150-{
151- if(wait != NULL) *wait = wait_val * 2;
152- return read_data16(addr, data);
153-}
154-
155-uint32_t DICTIONARY::read_data32w(uint32_t addr, int *wait)
156-{
157- if(wait != NULL) *wait = wait_val * 4;
158- return read_data32(addr, data);
159-}
160-
161-
162-void DICTIONARY::write_data8w(uint32_t addr, uint32_t data, int *wait)
163-{
164- if(wait != NULL) *wait = wait_val;
165- write_data8(addr, data);
166-}
167-
168-void DICTIONARY::write_data16w(uint32_t addr, uint32_t data, int *wait)
169-{
170- if(wait != NULL) *wait = wait_val * 2;
171- write_data16(addr, data);
172-}
173-
174-void DICTIONARY::write_data32w(uint32_t addr, uint32_t data, int *wait)
175-{
176- if(wait != NULL) *wait = wait_val * 4;
177- write_data32(addr, data);
178-}
179141
180142 void DICTIONARY::write_io8(uint32_t addr, uint32_t data)
181143 {
@@ -222,9 +184,6 @@ void DICTIONARY::write_signal(int ch, uint32_t data, uint32_t mask)
222184 case SIG_FMTOWNS_DICTBANK:
223185 dict_bank = (uint8_t)(data & 0x0f);
224186 break;
225- case SIG_FMTOWNS_SET_MEMWAIT:
226- wait_val = (int)data;
227- break;
228187 }
229188 }
230189
@@ -237,9 +196,6 @@ uint32_t DICTIONARY::read_signal(int ch)
237196 case SIG_FMTOWNS_DICTBANK:
238197 return (uint32_t)(dict_bank & 0x0f);
239198 break;
240- case SIG_FMTOWNS_SET_MEMWAIT:
241- return (uinrt32_t)wait_val;
242- break;
243199 }
244200 return 0x00;
245201 }
@@ -254,7 +210,6 @@ bool DICTIONARY::process_state(FILEIO* state_fio, bool loading)
254210 if(!state_fio->StateCheckInt32(this_device_id)) {
255211 return false;
256212 }
257- state_fio->StateValue(wait_val);
258213 state_fio->StateValue(dict_bank);
259214 state_fio->StateValue(bankd0_dict);
260215 state_fio->StateArray(dict_ram, sizeof(dict_ram), 1);
--- a/source/src/vm/fmtowns/towns_dictionary.h
+++ b/source/src/vm/fmtowns/towns_dictionary.h
@@ -28,7 +28,6 @@ protected:
2828
2929 bool bankd0_dict;
3030 uint8_t dict_bank;
31- int wait_val;
3231
3332 bool cmos_dirty;
3433
@@ -46,18 +45,10 @@ public:
4645 uint32_t read_data16(uint32_t addr);
4746 uint32_t read_data32(uint32_t addr);
4847
49- uint32_t read_data8w(uint32_t addr, int* wait);
50- uint32_t read_data16w(uint32_t addr, int* wait);
51- uint32_t read_data32w(uint32_t addr, int* wait);
52-
5348 void write_data8(uint32_t addr, uint32_t data);
5449 void write_data16(uint32_t addr, uint32_t data);
5550 void write_data32(uint32_t addr, uint32_t data);
5651
57- void write_data8w(uint32_t addr, uint32_t data, int* wait);
58- void write_data16w(uint32_t addr, uint32_t data, int* wait);
59- void write_data32w(uint32_t addr, uint32_t data, int* wait);
60-
6152 void write_io8(uint32_t addr, uint32_t data);
6253 void read_io8(uint32_t addr, uint32_t data);
6354
--- a/source/src/vm/fmtowns/towns_sysrom.cpp
+++ b/source/src/vm/fmtowns/towns_sysrom.cpp
@@ -24,15 +24,12 @@ void SYSROM::initialize()
2424 fio->Fread(rom, sizeof(rom), 1);
2525 fio->Fclose();
2626 }
27-
28- wait_val = 3;
2927 map_dos = true;
3028 }
3129
3230
3331 void SYSROM::reset()
3432 {
35- //wait_val = 6; // OK?
3633 //map_dos = true;
3734 }
3835
@@ -74,9 +71,6 @@ void SYSROM::write_signal(int ch, uint32_t data, uint32_t mask)
7471 case SIG_FMTOWNS_SYSROMSEL:
7572 map_dos = ((data & mask) == 0);
7673 break;
77- case SIG_FMTOWNS_SET_MEMWAIT:
78- wait_val = (int)data;
79- break;
8074 }
8175 }
8276
@@ -86,24 +80,9 @@ uint32_t SYSROM::read_signal(int ch)
8680 case SIG_FMTOWNS_SYSROMSEL:
8781 return ((map_dos) ? 0x00 : 0x02);
8882 break;
89- case SIG_FMTOWNS_SET_MEMWAIT:
90- return (uint32_t)wait_val;
91- break;
9283 }
9384 return 0x00;
9485 }
95-
96-uint32_t SYSROM::read_data8w(uint32_t addr, int *wait)
97-{
98- if(wait != NULL) *wait = wait_val;
99- return read_data8(addr, data);
100-}
101-
102-void SYSROM::write_data8w(uint32_t addr, uint32_t data, int *wait)
103-{
104- if(wait != NULL) *wait = wait_val;
105- write_data8(addr, data);
106-}
10786
10887 #define STATE_VERSION 1
10988
@@ -115,7 +94,6 @@ bool SYSROM::process_state(FILEIO* state_fio, bool loading)
11594 if(!state_fio->StateCheckInt32(this_device_id)) {
11695 return false;
11796 }
118- state_fio->StateValue(wait_val);
11997 state_fio->StateValue(map_dos);
12098 state_fio->StateArray(ram, sizeof(ram), 1);
12199 return true;
--- a/source/src/vm/fmtowns/towns_sysrom.h
+++ b/source/src/vm/fmtowns/towns_sysrom.h
@@ -21,8 +21,7 @@ class SYSROM : public DEVICE
2121 protected:
2222 uint8_t rom[0x40000]; // 256KB
2323 uint8_t ram[0x10000]; // 64KB
24- int wait_val;
25-
24+
2625 bool map_dos;
2726
2827 public:
@@ -35,10 +34,8 @@ public:
3534 void reset();
3635
3736 uint32_t read_data8(uint32_t addr);
38- uint32_t read_data8w(uint32_t addr, int* wait);
3937
4038 void write_data8(uint32_t addr, uint32_t data);
41- void write_data8w(uint32_t addr, uint32_t data, int* wait);
4239
4340 void write_signal(int ch, uint32_t data, uint32_t mask);
4441 uint32_t read_signal(int ch);
Show on old repository browser