OSDN Git Service

f1733bcfbcc4f1ac37b8ab1660da3b06a0383b07
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / towns_crtc.h
1 /*
2         Skelton for retropc emulator
3
4         Author : Kyuma Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2016.12.28 -
6
7         [ FM-Towns CRTC ]
8         History: 2016.12.28 Initial from HD46505 .
9 */
10
11 #ifndef _TOWNS_CRTC_H_
12 #define _TOWNS_CRTC_H_
13
14 #include "../vm.h"
15 #include "../emu.h"
16 #include "device.h"
17
18 /*
19  * I/O Address :
20  *  0440H : Register address (8bit W/O : bit7 to 5 must be '0').
21  *  0442H : Register data LOW  (8bit W/O).
22  *  0443H : Register data HIGH (8bit W/O).
23  * Interrupts (8259) :
24  *  #11 : VSYNC.
25  * Registers description:
26  *  Note1: Values are hex, register numbers are decimal.
27  *  Note2: Register #00 to #16 ,#18, #22 and #25 to #26 has 11bit.
28  *         #17, #19 to #21, #23 to #24 and #27 has 16bit.
29  *         #28 has bit 15,14  and 7 to 0.
30  *         #29 has 4bit.
31  *         #31 has bit15 and bit 8 to 0.
32  *        
33  *  #00 / bit 7 - 1 : HSW1 (Bit 10 to 8 and 0 must be '0')
34  *  #01 / bit 7 - 1 : HSW2 (Bit 10 to 8 and 0 must be '0')
35  *  #02 / ??
36  *  #03 / ??
37  *  #04 / bit10 - 1 : HST  (Bit 0 bust be '1')
38  *  #05 / bit 4 - 0 : VST1 (Bit 10 to 5 must be '0')
39  *  #06 / bit 4 - 0 : VST2 (Bit 10 to 5 must be '0')
40  *  #07 / bit 4 - 0 : EET  (Bit 10 to 5 must be '0')
41  *  #08 / bit10 - 0 : VST
42  *  #09 / bit10 - 0 : HDS0 (Layer 0)
43  *  #10 / bit10 - 0 : HDE0 (Layer 0)
44  *  #11 / bit10 - 0 : HDS1 (Layer 1)
45  *  #12 / bit10 - 0 : HDE1 (Layer 1)
46  *  #13 / bit10 - 0 : VDS0 (Layer 0)
47  *  #14 / bit10 - 0 : VDE0 (Layer 0)
48  *  #15 / bit10 - 0 : VDS1 (Layer 1)
49  *  #16 / bit10 - 0 : VDE1 (Layer 1)
50  *  #17 / bit15 - 0 : FA0  (Layer 0) 
51  *  #18 / bit10 - 0 : HAJ0 (Layer 0) 
52  *  #19 / bit15 - 0 : FO0  (Layer 0) 
53  *  #20 / bit15 - 0 : LO0  (Layer 0) 
54  *  #21 / bit15 - 0 : FA1  (Layer 1) 
55  *  #22 / bit10 - 0 : HAJ1 (Layer 1) 
56  *  #23 / bit15 - 0 : FO1  (Layer 1) 
57  *  #24 / bit15 - 0 : LO1  (Layer 1)
58  *  #25 / bit10 - 0 : EHAJ (External horizonal sync adjusting)
59  *  #26 / bit10 - 0 : EVAJ (External horizonal sync adjusting)
60  *  #27 / bit15 - 0 : bit15-12 : ZV1 / bit11-8 : ZH1 / bit7-4 : ZV0 / bit3-0 : ZH0 (Zooming)
61  *  #28 / bit15 : START ('1' = START) / bit14 : ESYN ('0' = Internal)
62  *        bit7 : ESM1 ('0'=Impose / '1' = Digitize) / bit 6 : ESM0
63  *        bit5 : CEN1 ('1' = Enable) / bit4 : CEN0
64  *        bit3-2 : CL1 (Colors : 00 = ND / 01 = 32768x2 / 10 = 32768x1 / 11 = 256x1 or 16x2)
65  *        bit1-0 : CL0
66  *  #29 / bit3-2 : SCSEL (Clock divide = 2 * (SCSEL + 1)).
67  *        bit1-0 : CLKSEL (00 = 28.6363MHz / 01 = 24.5454MHz / 10 = 25.175MHz / 11 = 21.0525MHz)
68  *  #30 / Status register (RO): 
69  *        bit15 : DSPTV1 / bit14 : DSPTV0 (VDISP = '1')
70  *        bit13 : DSPTH1 / bit12 : DSPTH0 (HDISP = '1')
71  *        bit11 : FIELD (Field number)
72  *        bit10 : VSYNC / bit9 : HSYNC ('1' = ACTIVE)
73  *        bit8  : VIN ('1' = EXTERNAL VIDEO has exists)
74  *       Dummy register  (WO):
75  *        bit3 : FR3 ('1' = Halve tone) /  bit2 : FR2 ('1' = Using sync generator)
76  *        bit1 : VCRDEN ('1' = Video card enable) / bit0 : SCEN ('1' = Sub carry enable)
77  *
78  *  #31 / bit15 = RETRG ('1' = Re-Trigger) / bit8-0 : PM (Pulse width : Width = PM * Clock).
79  */
80 /*
81  * Around Video Out.
82  *  I/O 044CH : Digital palette modified flags.
83  *      I/O 0448H (WO) : Register Address.
84  *      I/O 044AH (WO) : Register Data.
85  *  Registers:
86  *   #00 : Control registers.
87  *   #01 : Priority registers.
88  */
89 #define TOWNS_CRTC_MAX_LINES  1024
90 #define TOWNS_CRTC_MAX_PIXELS 1024
91 namespace FMTOWNS {
92
93         enum {
94                 TOWNS_CRTC_REG_HSW1 = 0,
95                 TOWNS_CRTC_REG_HSW2 = 1,
96                 TOWNS_CRTC_REG_HST  = 4,
97                 TOWNS_CRTC_REG_VST1,
98                 TOWNS_CRTC_REG_VST2,
99                 TOWNS_CRTC_REG_EET,
100         
101                 TOWNS_CRTC_REG_VST, // 8
102                 TOWNS_CRTC_REG_HDS0,
103                 TOWNS_CRTC_REG_HDE0,
104                 TOWNS_CRTC_REG_HDS1,
105                 TOWNS_CRTC_REG_HDE1,
106                 TOWNS_CRTC_REG_VDS0,
107                 TOWNS_CRTC_REG_VDE0,
108                 TOWNS_CRTC_REG_VDS1,
109         
110                 TOWNS_CRTC_REG_VDE1,
111                 TOWNS_CRTC_REG_FA0,
112                 TOWNS_CRTC_REG_HAJ0,
113                 TOWNS_CRTC_REG_FO0,
114                 TOWNS_CRTC_REG_LO0,
115                 TOWNS_CRTC_REG_FA1,
116                 TOWNS_CRTC_REG_HAJ1,
117                 TOWNS_CRTC_REG_FO1,
118         
119                 TOWNS_CRTC_REG_LO1,
120                 TOWNS_CRTC_REG_EHAJ,
121                 TOWNS_CRTC_REG_EVAJ,
122                 TOWNS_CRTC_REG_ZOOM,
123                 TOWNS_CRTC_REG_DISPMODE, // 28
124                 TOWNS_CRTC_REG_CLK, // 29
125                 TOWNS_CRTC_REG_DUMMY, // 30
126                 TOWNS_CRTC_REG_CTRL, // 31
127         };
128
129         enum {
130                 DISPMODE_NONE = 0,
131                 DISPMODE_32768_2,
132                 DISPMODE_32768_1,
133                 DISPMODE_256_OR_16,
134         };
135 }
136
137 namespace FMTOWNS {
138 class TOWNS_CRTC : public DEVICE
139 {
140 private:
141         // output signals
142         outputs_t outputs_int_vsync;  // Connect to int 11.
143         uint16_t regs[32];      // I/O 0442H, 0443H
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         
152         double crtc_clock; // 
153         // They are not saved.Must be calculate when loading.
154         double horiz_us, next_horiz_us; // (HST + 1) * clock
155         double horiz_width_posi_us, horiz_width_nega_us; // HSW1, HSW2
156         double vert_us, next_vert_us; // (VST +1) * horiz_us / 2.0
157         double vstart_us;
158         double vert_sync_pre_us; // VST1 * horiz_us / 2.0
159         double vert_sync_end_us; // VST2 * horiz_us / 2.0
160         // End
161
162         double frames_per_sec;
163
164         uint32_t vstart_addr[2];  // VSTART ADDRESS
165     uint32_t hstart_words[2]; // HSTART ((HDS[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
166     uint32_t hend_words[2];   // HEND   ((HDE[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
167     uint32_t vstart_lines[2]; // VSTART ((VDS[01] * clock) : Horizonal offset words (Related by VH[01]).
168     uint32_t vend_lines[2];   // VEND   ((VDE[01] * clock) : Horizonal offset words (Related by VH[01]).
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];
175         
176         uint32_t line_count[2]; // Separate per layer.
177         
178         int vert_line_count; // Not separate per layer.Total count.
179
180         int buffer_num; // Frame buffer number.
181         // Note: To display to real screen, use blending of OpenGL/DirectX
182         //       from below framebuffers per layer if you can.
183         //       And, recommand to use (hardware) shader to rendering (= not to use framebuffer of below) if enabled.
184         //       Not recommanded to use draw_screen() type rendering.
185         //       Rendering precesses may be heavily to use only CPU (I think). 20170107 K.Ohta.
186         
187         // Not Saved?.
188         uint8_t layer_colors[2];
189         uint16_t *vram_ptr[2];   // Layer [01] address.
190         uint32_t vram_size[2];   // Layer [01] size [bytes].
191         uint32_t vram_offset[2]; // Layer [01] address offset.
192         
193         uint32_t layer_virtual_width[2];
194         uint32_t layer_virtual_height[2];
195         uint32_t layer_display_width[2];
196         uint32_t layer_display_height[2];
197         // End.
198         
199         bool vdisp, vblank, vsync, hsync, hdisp, frame_in;
200
201         // Video output controller (I/O 0448H, 044AH)
202         // Register 00 : Display mode.
203         bool display_on[2]; // CL11-CL00 : bit3-0
204         bool one_layer_mode; // PMODE : bit4
205         // Register 11: Priority mode.
206         uint8_t vout_palette_mode;
207         bool vout_ys;
208         bool video_brightness; // false = high.
209         bool layer1_front; // if false, layer 0 is front.
210         
211         // Video output registers. May be split to separate files?
212         // FMR50 Compatible registers. They are mostly dummy.
213
214         // MMIO? 000C:FF80H
215         uint8_t r50_mix_reg;
216         // MMIO? 000C:FF81H
217         uint8_t r50_update_mode;
218         // MMIO? 000C:FF82H Not dummy?
219         uint8_t r50_dispmode;
220         // MMIO? 000C:FF83H Not dummy?
221         uint8_t r50_pagesel;
222         // MMIO? 000C:FF86H Not dummy?
223         uint8_t r50_status;
224         // I/O FDA0H Not Dummy?
225         //uint8_t r50_sub_statreg;
226
227         
228         // Others.
229         uint8_t video_out_reg_addr;  // I/O 0448H
230         uint8_t video_out_reg_data;  // I/O 044AH
231         uint8_t video_out_regs[2];
232         // End.
233
234         
235         // 
236         // Event IDs. Saved.
237         int event_id_hsync;
238         int event_id_hsw;
239         //int event_id_hsw1; //??
240         //int event_id_hsw2; //??
241         int event_id_vsync;
242         int event_id_vstart;
243         int event_id_vst1;
244         int event_id_vst2;
245         int event_id_vblank;
246         
247         void set_display(bool val);
248         void set_vblank(bool val);
249         void set_vsync(bool val);
250         void set_hsync(bool val);
251
252 protected:
253         bool render_a_line(int layer, int linenum, int xoffset, uint8_t *vramptr, uint32_t words);
254         void render_line_16(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words);
255         void render_line_256(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words);
256         void render_line_32768(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words);
257         void render_clear(int layer, scrntype_t *framebuffer);
258         
259 public:
260         TOWNS_CRTC(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
261         {
262                 initialize_output_signals(&outputs_int_vsync);
263                 set_device_name(_T("FM-Towns CRTC"));
264         }
265         ~TOWNS_CRTC() {}
266
267         void initialize();
268         void reset();
269         
270         void write_signal(int id, uint32_t data, uint32_t mask);
271         uint32_t read_signal(int ch);
272
273         void write_io8(uint32_t addr, uint32_t data);
274         uint32_t read_io8(uint32_t addr);
275
276         void write_io16(uint32_t addr, uint32_t data);
277         uint32_t read_io16(uint32_t addr);
278         
279         uint32_t read_data8(uint32_t addr);
280         uint32_t read_data16(uint32_t addr);
281         uint32_t read_data32(uint32_t addr);
282         
283         void write_data8(uint32_t addr, uint32_t data);
284         void write_data16(uint32_t addr, uint32_t data);
285         void write_data32(uint32_t addr, uint32_t data);
286         void event_callback(int event_id, int err);
287         //void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame);
288         void save_state(FILEIO* state_fio);
289         bool load_state(FILEIO* state_fio);
290         // unique function
291         void set_context_vsync(DEVICE* device, int id, uint32_t mask)
292         {
293                 register_output_signal(&outputs_vsync, device, id, mask);
294         }
295         uint16_t* get_regs_ptr()
296         {
297                 return regs;
298         }
299
300 };
301 }
302
303 #endif
304