2 * FM77AV/FM16β ALU [mb61vh010.h]
4 * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
7 * Mar 28, 2015 : Initial
11 #ifndef _VM_FM77AV_16beta_ALU_H_
12 #define _VM_FM77AV_16beta_ALU_H_
15 #include "../device.h"
18 ALU_WRITE_PROXY = 0x00000,
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,
54 EVENT_MB61VH010_BUSY_ON = 0,
55 EVENT_MB61VH010_BUSY_OFF
61 class MB61VH010: public DEVICE {
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)
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)
88 uint32_t screen_width;
89 uint32_t screen_height;
93 bool disable_flags[4];
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);
114 MB61VH010(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
117 direct_access_offset = 0;
118 set_device_name(_T("MB61VH010 ALU"));
122 void save_state(FILEIO *state_fio);
123 bool load_state(FILEIO *state_fio);
124 void decl_state(void);
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);
133 //void update_config(void);
135 void set_context_memory(DEVICE *p)
139 void set_direct_access_offset(uint32_t offset)
141 direct_access_offset = offset;
145 inline void MB61VH010::put_dot(int x, int y)
147 const uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
153 if((command_reg & 0x80) == 0) return; // Not compare.
154 if((x < 0) || (y < 0)) {
155 return; // Lower address
158 //if(y >= (int)screen_height) return; // Workaround of overflow
160 alu_addr = (y * screen_width + x) >> 3;
161 alu_addr = alu_addr + line_addr_offset.w.l;
163 alu_addr = alu_addr & 0x3fff;
165 alu_addr = alu_addr & 0x7fff;
168 mask8 = ~vmask[x & 7];
170 tmp8a = line_style.b.h & 0x80;
172 if(oldaddr != alu_addr) {
173 if(oldaddr == 0xffffffff) {
184 line_style.w.l <<= 1;
187 line_style.w.l |= 0x01;
192 inline void MB61VH010::put_dot8(int x, int y)
194 const uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
198 if((command_reg & 0x80) == 0) return; // Not compare.
199 if((x < 0) || (y < 0)) {
200 return; // Lower address
203 //if(y >= (int)screen_height) return; // Workaround of overflow
205 alu_addr = (y * screen_width + x) >> 3;
206 alu_addr = alu_addr + line_addr_offset.w.l;
208 alu_addr = alu_addr & 0x3fff;
210 alu_addr = alu_addr & 0x7fff;
213 if(oldaddr != alu_addr) {
214 if(oldaddr == 0xffffffff) {
215 if((line_style.b.h & 0x80) != 0) {
216 mask_reg &= ~vmask[x & 7];
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;
233 inline uint8_t MB61VH010::do_read(uint32_t addr, uint32_t bank)
237 //if(((1 << bank) & multi_page) != 0) return 0xff;
238 if(multi_flags[bank]) return 0xff;
240 if((addr & 0xffff) < 0x8000) {
241 raddr = (addr & 0x7fff) | (0x8000 * bank);
242 return target->read_data8(raddr + direct_access_offset);
245 raddr = (addr & 0x3fff) | (0x4000 * bank);
246 return target->read_data8(raddr + direct_access_offset);
251 inline void MB61VH010::do_write(uint32_t addr, uint32_t bank, uint8_t data)
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);
261 if((command_reg & 0x20) != 0) { // NAND
262 readdata = readdata & cmp_status_reg;
263 data = data & (~cmp_status_reg);
265 readdata = readdata & (~cmp_status_reg);
266 data = data & cmp_status_reg;
268 readdata = readdata | data;
273 if((addr & 0xffff) < 0x8000) {
274 raddr = (addr & 0x7fff) | (0x8000 * bank);
275 target->write_data8(raddr + direct_access_offset, readdata);
278 raddr = (addr & 0x3fff) | (0x4000 * bank);
279 target->write_data8(raddr + direct_access_offset, readdata);
283 #endif // _VM_FM77AV_16beta_ALU_H_