2 Skelton for retropc emulator
4 Author : Kyuma Ohta <whatisthis.sowhat _at_ gmail.com>
8 History: 2017.01.16 Initial.
13 #include "./towns_common.h"
19 void TOWNS_VRAM::initialize()
21 memset(vram, 0x00, sizeof(vram));
24 void TOWNS_VRAM::reset()
28 __DECL_VECTORIZED_LOOP
29 for(int i = 0; i < 8; i++) {
30 packed_pixel_mask_reg[i] = 0xff;
32 vram_access_reg_addr = 0;
37 void TOWNS_VRAM::write_memory_mapped_io8(uint32_t addr, uint32_t data)
39 const uint32_t naddr = calc_std_address_offset(addr);
40 const uint8_t mask = packed_pixel_mask_reg[naddr & 3];
43 uint8_t nd = vram[naddr];
54 void TOWNS_VRAM::write_memory_mapped_io16(uint32_t addr, uint32_t data)
57 const uint32_t maddr = addr & 1;
58 const uint32_t paddr0 = calc_std_address_offset(addr);
59 const uint32_t paddr1 = calc_std_address_offset(addr + 1);
65 dmask.b.l = packed_pixel_mask_reg[paddr0 & 7];
66 dmask.b.h = packed_pixel_mask_reg[paddr1 & 7];
68 xdata.b.l = vram[paddr0];
69 xdata.b.h = vram[paddr1];
73 xdata.w &= ~(dmask.w);
78 vram[paddr0] = xdata.b.l;
79 vram[paddr1] = xdata.b.h;
85 void TOWNS_VRAM::write_memory_mapped_io32(uint32_t addr, uint32_t data)
88 uint32_t maddr = addr & 3;
89 uint32_t paddr0, paddr1, paddr2, paddr3;
93 __LIKELY_IF(maddr == 0) { // Aligned
94 paddr0 = calc_std_address_offset(addr);
95 dmask.read_4bytes_le_from(&(packed_pixel_mask_reg[0]));
96 xdata.read_4bytes_le_from(&(vram[paddr0]));
99 paddr0 = calc_std_address_offset(addr);
100 paddr1 = calc_std_address_offset(addr + 1);
101 paddr2 = calc_std_address_offset(addr + 2);
102 paddr3 = calc_std_address_offset(addr + 3);
104 dmask.b.l = packed_pixel_mask_reg[paddr0 & 7];
105 dmask.b.h = packed_pixel_mask_reg[paddr1 & 7];
106 dmask.b.h2 = packed_pixel_mask_reg[paddr2 & 7];
107 dmask.b.h3 = packed_pixel_mask_reg[paddr3 & 7];
109 xdata.b.l = vram[paddr0];
110 xdata.b.h = vram[paddr1];
111 xdata.b.h2 = vram[paddr2];
112 xdata.b.h3 = vram[paddr3];
117 xdata.d &= ~(dmask.d);
121 __LIKELY_IF(maddr == 0) { // Aligned
122 xdata.write_4bytes_le_to(&(vram[paddr0]));
125 vram[paddr0] = xdata.b.l;
126 vram[paddr1] = xdata.b.h;
127 vram[paddr2] = xdata.b.h2;
128 vram[paddr3] = xdata.b.h3;
134 uint32_t TOWNS_VRAM::read_memory_mapped_io8(uint32_t addr)
137 const uint32_t naddr = calc_std_address_offset(addr);
138 uint32_t n = vram[naddr];
143 uint32_t TOWNS_VRAM::read_memory_mapped_io16(uint32_t addr)
145 const uint32_t paddr0 = calc_std_address_offset(addr);
146 const uint32_t paddr1 = calc_std_address_offset(addr + 1);
147 //const uint32_t maddr = addr & 1;
151 data.b.l = vram[paddr0];
152 data.b.h = vram[paddr1];
154 return (uint32_t)(data.w);
157 uint32_t TOWNS_VRAM::read_memory_mapped_io32(uint32_t addr)
160 __LIKELY_IF((addr & 3) == 0) { // Aligned
161 const uint32_t paddr = calc_std_address_offset(addr);
162 data.read_4bytes_le_from(&(vram[paddr]));
164 const uint32_t paddr0 = calc_std_address_offset(addr);
165 const uint32_t paddr1 = calc_std_address_offset(addr + 1);
166 const uint32_t paddr2 = calc_std_address_offset(addr + 2);
167 const uint32_t paddr3 = calc_std_address_offset(addr + 3);
168 data.b.l = vram[paddr0];
169 data.b.h = vram[paddr1];
170 data.b.h2 = vram[paddr2];
171 data.b.h3 = vram[paddr3];
176 void TOWNS_VRAM::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
178 __LIKELY_IF(wait != NULL) {
179 *wait = 0; // WAIT SETS by TOWNS_MEMORY:: .
181 write_memory_mapped_io8(addr, data);
184 void TOWNS_VRAM::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
186 __LIKELY_IF(wait != NULL) {
187 *wait = 0; // WAIT SETS by TOWNS_MEMORY:: .
189 write_memory_mapped_io16(addr, data);
192 void TOWNS_VRAM::write_dma_data32w(uint32_t addr, uint32_t data, int* wait)
194 __LIKELY_IF(wait != NULL) {
195 *wait = 0; // WAIT SETS by TOWNS_MEMORY:: .
197 write_memory_mapped_io32(addr, data);
200 uint32_t TOWNS_VRAM::read_dma_data8w(uint32_t addr, int* wait)
202 __LIKELY_IF(wait != NULL) {
203 *wait = 0; // WAIT SETS by TOWNS_MEMORY:: .
205 return read_memory_mapped_io8(addr);
208 uint32_t TOWNS_VRAM::read_dma_data16w(uint32_t addr, int* wait)
210 __LIKELY_IF(wait != NULL) {
211 *wait = 0; // WAIT SETS by TOWNS_MEMORY:: .
213 return read_memory_mapped_io16(addr);
216 uint32_t TOWNS_VRAM::read_dma_data32w(uint32_t addr, int* wait)
218 __LIKELY_IF(wait != NULL) {
219 *wait = 0; // WAIT SETS by TOWNS_MEMORY:: .
221 return read_memory_mapped_io32(addr);
224 void TOWNS_VRAM::write_signal(int id, uint32_t data, uint32_t mask)
230 void TOWNS_VRAM::write_io8(uint32_t address, uint32_t data)
232 switch(address & 0xffff) {
234 vram_access_reg_addr = data & 3;
235 // out_debug_log(_T("VRAM ACCESS(0458h)=%02X"), data);
238 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 0] = data;
239 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 4] = data;
240 // out_debug_log(_T("VRAM MASK(045Ah)=%08X"), packed_pixel_mask_reg.d);
243 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 1] = data;
244 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 5] = data;
245 // out_debug_log(_T("VRAM MASK(045Bh)=%08X"), packed_pixel_mask_reg.d);
248 // ToDo: Implement around VRAM cache.
249 // VCMEN (Disabled) : Bit0
254 void TOWNS_VRAM::write_io16(uint32_t address, uint32_t data)
258 switch(address & 0xffff) {
260 vram_access_reg_addr = data & 3;
266 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 0] = w.b.l;
267 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 1] = w.b.h;
268 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 4] = w.b.l;
269 packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 5] = w.b.h;
276 write_io8(0x05ee, n.b.l);
282 uint32_t TOWNS_VRAM::read_io8(uint32_t address)
284 switch(address & 0xffff) {
286 return vram_access_reg_addr;
290 uint8_t v = packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 0];
296 uint8_t v = packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 1];
301 // ToDo: Implement around VRAM cache.
302 // Bit7 = 0 if ready to turn on/off VRAM cache.
303 // VCMEN (Disabled) : Bit0
304 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX and after Pentium.
305 // Still Disabled VRAM feature and disable VCMEN.
314 uint32_t TOWNS_VRAM::read_io16(uint32_t address)
316 switch(address & 0xffff) {
318 return vram_access_reg_addr;
323 w.b.l = packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 0];
324 w.b.h = packed_pixel_mask_reg[(vram_access_reg_addr << 1) + 1];
325 return (uint32_t)(w.w);
331 n.b.l = read_io8(0x05ee);
340 void TOWNS_VRAM::get_data_from_vram(bool is_single, uint32_t offset, uint32_t bytes, uint8_t* dst)
342 __UNLIKELY_IF((bytes == 0) || (bytes > (TOWNS_CRTC_MAX_PIXELS * sizeof(uint16_t))) || (dst == nullptr)) {
345 uint32_t addr = offset & TOWNS_VRAM_ADDR_MASK;
346 uint8_t* p = ___assume_aligned(dst, 16);
350 addr |= (1 << (TOWNS_VRAM_ADDR_SHIFT + 1));
351 __DECL_ALIGNED(32) uint8_t cache[16];
352 __DECL_ALIGNED(32) uint8_t cache2[16];
353 for(int i = bytes; i >= 16; i -= 16) {
354 for(int j = 0; j < 16; j++) {
355 cache[j] = vram[calc_std_address_offset(addr + j)];
357 __DECL_VECTORIZED_LOOP
358 for(int j = 0; j < 16; j++) {
364 bytes = bytes & 0x0f; // MOD
365 for(int j = 0; j < bytes; j++) {
366 cache2[j] = vram[calc_std_address_offset(addr + j)];
368 for(int j = 0; j < bytes; j++) {
372 __LIKELY_IF((addr + bytes) <= (TOWNS_VRAM_ADDR_MASK + 1)) {
374 memcpy(p, &(vram[addr]), bytes);
376 uint32_t nb = (addr + bytes) - (TOWNS_VRAM_ADDR_MASK + 1);
377 __LIKELY_IF(nb < bytes) {
378 memcpy(p, &(vram[addr]), bytes - nb);
379 __LIKELY_IF(nb > 0) {
380 memcpy(&(p[bytes - nb]), &(vram[0]), nb);
384 memcpy(p, &(vram[addr]), bytes - nb);
391 bool TOWNS_VRAM::set_buffer_to_vram(uint32_t offset, uint8_t *buf, int words)
393 // uint32_t offset2 = calc_std_address_offset(offset);
394 const uint32_t offset2 = offset & TOWNS_VRAM_ADDR_MASK;
395 // if(words > 16) return false;
396 __UNLIKELY_IF(words <= 0) return false;
397 uint8_t* p = &(vram[offset2]);
400 __LIKELY_IF((offset2 + (words << 1)) <= (TOWNS_VRAM_ADDR_MASK + 1)) {
401 memcpy(p, buf, words << 1);
403 int nb = (TOWNS_VRAM_ADDR_MASK + 1) - offset2;
405 int nnb = (words << 1) - nb;
406 __LIKELY_IF(nnb > 0) {
407 memcpy(vram, &(buf[nb]), nnb);
414 bool TOWNS_VRAM::get_vram_to_buffer(uint32_t offset, uint8_t *buf, int words)
416 //uint32_t offset2 = calc_std_address_offset(offset);
417 const uint32_t offset2 = offset & TOWNS_VRAM_ADDR_MASK;
418 // if(words > 16) return false;
419 __UNLIKELY_IF(words <= 0) return false;
422 uint8_t* p = &(vram[offset2]);
423 __LIKELY_IF((offset2 + (words << 1)) <= (TOWNS_VRAM_ADDR_MASK + 1)) {
424 memcpy(buf, p, words << 1);
426 uint32_t nb = (TOWNS_VRAM_ADDR_MASK + 1) - offset2;
428 int nnb = (words << 1) - nb;
429 __LIKELY_IF(nnb > 0) {
430 memcpy(&(buf[nb]), vram, nnb);
437 #define STATE_VERSION 3
439 bool TOWNS_VRAM::process_state(FILEIO* state_fio, bool loading)
441 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
445 if(!state_fio->StateCheckInt32(this_device_id)) {
451 state_fio->StateValue(vram_access_reg_addr);
452 state_fio->StateArray(packed_pixel_mask_reg, sizeof(packed_pixel_mask_reg), 1);
454 state_fio->StateArray(vram, sizeof(vram), 1);