OSDN Git Service

[Qt][OpenGL][WIP] GL4.3: Implementing texture buffer with mapping.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / mb61vh010.h
1 /*
2  * FM77AV/FM16β ALU [mb61vh010.h]
3  *
4  * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
5  * License: GPLv2
6  * History:
7  *   Mar 28, 2015 : Initial
8  *
9  */
10
11 #ifndef _VM_FM77AV_16beta_ALU_H_
12 #define _VM_FM77AV_16beta_ALU_H_
13
14
15 #include "../device.h"
16
17 enum {
18         ALU_WRITE_PROXY = 0x00000,
19         ALU_CMDREG = 0x10000,
20         ALU_LOGICAL_COLOR,
21         ALU_WRITE_MASKREG,
22         ALU_CMP_STATUS_REG,
23         ALU_BANK_DISABLE,
24         ALU_TILEPAINT_B,
25         ALU_TILEPAINT_R,
26         ALU_TILEPAINT_G,
27         ALU_TILEPAINT_L,
28         ALU_OFFSET_REG_HIGH,
29         ALU_OFFSET_REG_LO,
30         ALU_LINEPATTERN_REG_HIGH,
31         ALU_LINEPATTERN_REG_LO,
32         ALU_LINEPOS_START_X_HIGH,
33         ALU_LINEPOS_START_X_LOW,  
34         ALU_LINEPOS_START_Y_HIGH,
35         ALU_LINEPOS_START_Y_LOW,  
36         ALU_LINEPOS_END_X_HIGH,
37         ALU_LINEPOS_END_X_LOW,  
38         ALU_LINEPOS_END_Y_HIGH,
39         ALU_LINEPOS_END_Y_LOW,
40         ALU_CMPDATA_REG,
41 };
42
43 enum {
44         SIG_ALU_BUSYSTAT = 1,
45         SIG_ALU_400LINE,
46         SIG_ALU_MULTIPAGE,
47         SIG_ALU_PLANES,
48         SIG_ALU_X_WIDTH,
49         SIG_ALU_Y_HEIGHT,
50         SIG_ALU_ENABLED,
51 };
52
53 enum {
54         EVENT_MB61VH010_BUSY_ON = 0,
55         EVENT_MB61VH010_BUSY_OFF
56 };
57
58 class VM;
59 class EMU;
60
61 class MB61VH010: public DEVICE {
62  protected:
63         DEVICE *target;
64
65         // Registers
66         uint8_t command_reg;        // D410 (RW)
67         uint8_t color_reg;          // D411 (RW)
68         uint8_t mask_reg;           // D412 (RW)
69         uint8_t cmp_status_reg;     // D413 (RO)
70         uint8_t cmp_color_data[8]; // D413-D41A (WO)
71         uint8_t bank_disable_reg;   // D41B (RW)
72         uint8_t tile_reg[4];        // D41C-D41F (WO)
73         uint8_t multi_page;
74         uint32_t direct_access_offset;  
75         pair_t  line_addr_offset; // D420-D421 (WO)
76         pair_t  line_pattern;     // D422-D423 (WO)
77         pair_t  line_xbegin;      // D424-D425 (WO)
78         pair_t  line_ybegin;      // D426-D427 (WO)
79         pair_t  line_xend;        // D428-D429 (WO)
80         pair_t  line_yend;        // D42A-D42B (WO)
81         
82         bool busy_flag;
83         int eventid_busy;
84
85         uint32_t planes;
86         uint32_t total_bytes;
87         bool is_400line;
88         uint32_t screen_width;
89         uint32_t screen_height;
90         uint32_t oldaddr;
91         uint32_t alu_addr;
92         pair_t line_style;
93         bool disable_flags[4];
94         bool multi_flags[4];
95         // ALU COMMANDS
96         inline uint8_t do_read(uint32_t addr,  uint32_t bank);
97         inline void do_write(uint32_t addr, uint32_t bank, uint8_t data);
98         void do_pset(uint32_t addr);
99         void do_blank(uint32_t addr);
100         void do_or(uint32_t addr);
101         void do_and(uint32_t addr);
102         void do_xor(uint32_t addr);
103         void do_not(uint32_t addr);
104         void do_tilepaint(uint32_t addr);
105         void do_compare(uint32_t addr);
106         void do_alucmds(uint32_t addr);
107         void do_alucmds_dmyread(uint32_t addr);
108         inline void put_dot(int x, int y);
109         inline void put_dot8(int x, int y);
110
111         // LINE
112         void do_line(void);
113  public:
114         MB61VH010(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
115         {
116                 target = NULL;
117                 direct_access_offset = 0;
118                 set_device_name(_T("MB61VH010 ALU"));
119         }
120         ~MB61VH010() {}
121
122         void save_state(FILEIO *state_fio);
123         bool load_state(FILEIO *state_fio);
124         void decl_state(void);
125         
126         void event_callback(int event_id, int err);
127         void write_data8(uint32_t id, uint32_t data);
128         uint32_t read_data8(uint32_t addr);
129         uint32_t read_signal(int id); 
130         void write_signal(int id, uint32_t data, uint32_t mask);
131         void initialize(void);
132         void reset(void);
133         //void update_config(void);
134         
135         void set_context_memory(DEVICE *p)
136         {
137                 target = p;
138         }
139         void set_direct_access_offset(uint32_t offset)
140         {
141                 direct_access_offset = offset;  
142         }
143 };      
144
145 inline void MB61VH010::put_dot(int x, int y)
146 {
147         const uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
148         uint8_t tmp8a;
149         uint8_t mask8;
150         
151         //bool updated;
152    
153         if((command_reg & 0x80) == 0) return; // Not compare.
154         if((x < 0) || (y < 0)) {
155                 return; // Lower address
156         }
157    
158         //if(y >= (int)screen_height) return; // Workaround of overflow
159         
160         alu_addr = (y * screen_width + x)  >> 3;
161         alu_addr = alu_addr + line_addr_offset.w.l;
162         if(!is_400line) {
163                 alu_addr = alu_addr & 0x3fff;
164         } else {
165                 alu_addr = alu_addr & 0x7fff;
166         }
167         
168         mask8 = ~vmask[x & 7];
169         //updated = false;
170         tmp8a = line_style.b.h & 0x80;
171         
172         if(oldaddr != alu_addr) {
173                 if(oldaddr == 0xffffffff) {
174                         if(tmp8a != 0) {
175                                 mask_reg &= mask8;
176                         }
177                         oldaddr = alu_addr;
178                 }
179                 do_alucmds(oldaddr);
180                 mask_reg = 0xff;
181                 oldaddr = alu_addr;
182                 //updated = true;
183         }
184         line_style.w.l <<= 1;
185         if(tmp8a != 0) {
186                 mask_reg &= mask8;
187                 line_style.w.l |= 0x01;
188         }
189         return;
190 }
191
192 inline void MB61VH010::put_dot8(int x, int y)
193 {
194         const uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
195         uint8_t tmp8a;
196         //bool updated;
197    
198         if((command_reg & 0x80) == 0) return; // Not compare.
199         if((x < 0) || (y < 0)) {
200                 return; // Lower address
201         }
202    
203         //if(y >= (int)screen_height) return; // Workaround of overflow
204         
205         alu_addr = (y * screen_width + x)  >> 3;
206         alu_addr = alu_addr + line_addr_offset.w.l;
207         if(!is_400line) {
208                 alu_addr = alu_addr & 0x3fff;
209         } else {
210                 alu_addr = alu_addr & 0x7fff;
211         }
212         //updated = false;
213         if(oldaddr != alu_addr) {
214                 if(oldaddr == 0xffffffff) {
215                         if((line_style.b.h & 0x80) != 0) {
216                                 mask_reg &= ~vmask[x & 7];
217                         }
218                         oldaddr = alu_addr;
219                 }
220                 do_alucmds(oldaddr);
221                 mask_reg = 0xff;
222                 oldaddr = alu_addr;
223                 //updated = true;
224         }
225         tmp8a = line_style.b.h;
226         mask_reg = mask_reg & ~tmp8a;
227         tmp8a = line_style.b.l;
228         line_style.b.l = line_style.b.h;
229         line_style.b.h = tmp8a;
230         return;
231 }
232
233 inline uint8_t MB61VH010::do_read(uint32_t addr, uint32_t bank)
234 {
235         uint32_t raddr;
236         
237         //if(((1 << bank) & multi_page) != 0) return 0xff;
238         if(multi_flags[bank]) return 0xff;
239         if(is_400line) {
240                 if((addr & 0xffff) < 0x8000) {
241                         raddr = (addr  & 0x7fff) | (0x8000 * bank);
242                         return target->read_data8(raddr + direct_access_offset);
243                 }
244         } else {
245                 raddr = (addr & 0x3fff) | (0x4000 * bank);
246                 return target->read_data8(raddr + direct_access_offset);
247         }
248         return 0xff;
249 }
250
251 inline void MB61VH010::do_write(uint32_t addr, uint32_t bank, uint8_t data)
252 {
253         uint32_t raddr;
254         uint8_t readdata;
255
256         //if(((1 << bank) & multi_page) != 0) return;
257         if(multi_flags[bank]) return;
258         if((command_reg & 0x40) != 0) { // Calculate before writing
259                 readdata = do_read(addr, bank);
260                 //readdata = data;
261                 if((command_reg & 0x20) != 0) { // NAND
262                         readdata = readdata & cmp_status_reg;
263                         data = data & (~cmp_status_reg);
264                 } else { // AND
265                         readdata = readdata & (~cmp_status_reg);
266                         data = data & cmp_status_reg;
267                 }
268                 readdata = readdata | data;
269         } else {
270                 readdata = data;
271         }
272         if(is_400line) {
273                 if((addr & 0xffff) < 0x8000) {
274                         raddr = (addr & 0x7fff) | (0x8000 * bank);
275                         target->write_data8(raddr + direct_access_offset, readdata);
276                 }
277         } else {
278                 raddr = (addr & 0x3fff) | (0x4000 * bank);
279                 target->write_data8(raddr + direct_access_offset, readdata);
280         }
281         return;
282 }
283 #endif // _VM_FM77AV_16beta_ALU_H_