00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00097 #include "StdAfx.h"
00098 #include "Cirrus.h"
00099 #include "System.h"
00100 #include "AliM1543C.h"
00101 #include "gui/gui.h"
00102
00103 static unsigned old_iHeight = 0, old_iWidth = 0, old_MSL = 0;
00104
00105 static const u8 ccdat[16][4] = {
00106 {0x00, 0x00, 0x00, 0x00},
00107 {0xff, 0x00, 0x00, 0x00},
00108 {0x00, 0xff, 0x00, 0x00},
00109 {0xff, 0xff, 0x00, 0x00},
00110 {0x00, 0x00, 0xff, 0x00},
00111 {0xff, 0x00, 0xff, 0x00},
00112 {0x00, 0xff, 0xff, 0x00},
00113 {0xff, 0xff, 0xff, 0x00},
00114 {0x00, 0x00, 0x00, 0xff},
00115 {0xff, 0x00, 0x00, 0xff},
00116 {0x00, 0xff, 0x00, 0xff},
00117 {0xff, 0xff, 0x00, 0xff},
00118 {0x00, 0x00, 0xff, 0xff},
00119 {0xff, 0x00, 0xff, 0xff},
00120 {0x00, 0xff, 0xff, 0xff},
00121 {0xff, 0xff, 0xff, 0xff},
00122 };
00123
00130 #define SET_TILE_UPDATED(xtile, ytile, value) \
00131 do \
00132 { \
00133 if(((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \
00134 state.vga_tile_updated[(xtile)][(ytile)] = value; \
00135 } while(0)
00136
00143 #define GET_TILE_UPDATED(xtile, ytile) \
00144 ((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) ? state.vga_tile_updated[(xtile)][(ytile)] : 0)
00145
00156 void CCirrus::run()
00157 {
00158 try
00159 {
00160
00161 bx_gui->init(state.x_tilesize, state.y_tilesize);
00162 for(;;)
00163 {
00164
00165 if(StopThread)
00166 return;
00167
00168 for (int i=0;i<10;i++)
00169 {
00170 bx_gui->lock();
00171 bx_gui->handle_events();
00172 bx_gui->unlock();
00173 Poco::Thread::sleep(10);
00174 }
00175
00176 bx_gui->lock();
00177 update();
00178 bx_gui->flush();
00179 bx_gui->unlock();
00180 }
00181 }
00182
00183 catch(Poco::Exception & e)
00184 {
00185 printf("Exception in Cirrus thread: %s.\n", e.displayText().c_str());
00186
00187
00188 }
00189 }
00190
00192 static unsigned int rom_max;
00193
00195 static u8 option_rom[65536];
00196
00198 static u32 cirrus_cfg_data[64] = {
00199 0x00a81013,
00200 0x011f0000,
00201 0x03000002,
00202 0x00000000,
00203 0xf8000000,
00204 0x00000000,
00205 0x00000000,
00206 0x00000000,
00207 0x00000000,
00208 0x00000000,
00209 0x00000000,
00210 0x00000000,
00211 0x00000000,
00212 0x00000000,
00213 0x00000000,
00214 0x281401ff,
00215 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00218 };
00219
00221 static u32 cirrus_cfg_mask[64] = {
00222 0x00000000,
00223 0x0000ffff,
00224 0x00000000,
00225 0x0000ffff,
00226 0xfc000000,
00227 0x00000000,
00228 0x00000000,
00229 0x00000000,
00230 0x00000000,
00231 0x00000000,
00232 0x00000000,
00233 0x00000000,
00234 0x00000000,
00235 0x00000000,
00236 0x00000000,
00237 0x000000ff,
00238 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00241 };
00242
00248 CCirrus::CCirrus(CConfigurator* cfg, CSystem* c, int pcibus, int pcidev) : CVGA(cfg, c, pcibus, pcidev)
00249 { }
00250
00254 void CCirrus::init()
00255 {
00256
00257 add_function(0, cirrus_cfg_data, cirrus_cfg_mask);
00258
00259 int i;
00260
00261
00262 memset((void*) &state, 0, sizeof(state));
00263
00264
00265 add_legacy_io(1, 0x3b4, 2);
00266 add_legacy_io(3, 0x3ba, 2);
00267 add_legacy_io(2, 0x3c0, 16);
00268 add_legacy_io(8, 0x3d4, 2);
00269 add_legacy_io(9, 0x3da, 1);
00270
00271
00272
00273 add_legacy_io(7, 0x500, 1);
00274 bios_message_size = 0;
00275 bios_message[0] = '\0';
00276
00277
00278 add_legacy_mem(4, 0xa0000, 128 * 1024);
00279
00280
00281 ResetPCI();
00282
00283
00284
00285 FILE* rom = fopen(myCfg->get_text_value("rom", "vgabios.bin"), "rb");
00286 if(!rom)
00287 {
00288 FAILURE_1(FileNotFound, "cirrus rom file %s not found.",
00289 myCfg->get_text_value("rom", "vgabios.bin"));
00290 }
00291
00292 rom_max = (unsigned) fread(option_rom, 1, 65536, rom);
00293 fclose(rom);
00294
00295
00296 add_legacy_mem(5, 0xc0000, rom_max);
00297
00298 state.vga_enabled = 1;
00299 state.misc_output.color_emulation = 1;
00300 state.misc_output.enable_ram = 1;
00301 state.misc_output.horiz_sync_pol = 1;
00302 state.misc_output.vert_sync_pol = 1;
00303
00304 state.attribute_ctrl.mode_ctrl.enable_line_graphics = 1;
00305
00306 state.line_offset = 80;
00307 state.line_compare = 1023;
00308 state.vertical_display_end = 399;
00309
00310 state.attribute_ctrl.video_enabled = 1;
00311 state.attribute_ctrl.color_plane_enable = 0x0f;
00312
00313 state.pel.dac_state = 0x01;
00314 state.pel.mask = 0xff;
00315
00316 state.graphics_ctrl.memory_mapping = 2;
00317
00318 state.sequencer.reset1 = 1;
00319 state.sequencer.reset2 = 1;
00320 state.sequencer.extended_mem = 1;
00321 state.sequencer.odd_even = 1;
00322
00323 state.memsize = 0x40000;
00324 state.memory = new u8[state.memsize];
00325 memset(state.memory, 0, state.memsize);
00326
00327 state.last_bpp = 8;
00328
00329 state.CRTC.reg[0x09] = 16;
00330 state.graphics_ctrl.memory_mapping = 3;
00331 state.vga_mem_updated = 1;
00332
00333 myThread = 0;
00334 printf("%s: $Id: Cirrus.cpp,v 1.21 2008/03/25 08:41:32 iamcamiel Exp $\n",
00335 devid_string);
00336 }
00337
00341 void CCirrus::start_threads()
00342 {
00343 if(!myThread)
00344 {
00345 myThread = new Poco::Thread("cirrus");
00346 printf(" %s", myThread->getName().c_str());
00347 StopThread = false;
00348 myThread->start(*this);
00349 }
00350 }
00351
00355 void CCirrus::stop_threads()
00356 {
00357
00358 StopThread = true;
00359 if(myThread)
00360 {
00361 printf(" %s", myThread->getName().c_str());
00362
00363 myThread->join();
00364
00365 delete myThread;
00366 myThread = 0;
00367 }
00368 }
00369
00373 CCirrus::~CCirrus()
00374 {
00375 stop_threads();
00376 }
00377
00381 u32 CCirrus::ReadMem_Legacy(int index, u32 address, int dsize)
00382 {
00383 u32 data = 0;
00384 switch(index)
00385 {
00386
00387 case 1:
00388 data = io_read(address + 0x3b4, dsize);
00389 break;
00390
00391
00392 case 2:
00393 data = io_read(address + 0x3c0, dsize);
00394 break;
00395
00396
00397 case 3:
00398 data = io_read(address + 0x3ba, dsize);
00399 break;
00400
00401
00402 case 4:
00403 data = legacy_read(address, dsize);
00404 break;
00405
00406
00407 case 5:
00408 data = rom_read(address, dsize);
00409 break;
00410
00411
00412 case 8:
00413 data = io_read(address + 0x3d4, dsize);
00414 break;
00415
00416
00417 case 9:
00418 data = io_read(address + 0x3da, dsize);
00419 break;
00420 }
00421
00422 return data;
00423 }
00424
00428 void CCirrus::WriteMem_Legacy(int index, u32 address, int dsize, u32 data)
00429 {
00430 switch(index)
00431 {
00432
00433 case 1:
00434 io_write(address + 0x3b4, dsize, data);
00435 return;
00436
00437
00438 case 2:
00439 io_write(address + 0x3c0, dsize, data);
00440 return;
00441
00442
00443 case 3:
00444 io_write(address + 0x3ba, dsize, data);
00445 return;
00446
00447
00448 case 4:
00449 legacy_write(address, dsize, data);
00450 return;
00451
00452
00453 case 7:
00454 bios_message[bios_message_size++] = (char) data & 0xff;
00455 if(((data & 0xff) == 0x0a) || ((data & 0xff) == 0x0d))
00456 {
00457 if(bios_message_size > 1)
00458 {
00459 bios_message[bios_message_size - 1] = '\0';
00460 printf("cirrus: %s\n", bios_message);
00461 }
00462
00463 bios_message_size = 0;
00464 }
00465
00466 return;
00467
00468
00469 case 8:
00470 io_write(address + 0x3d4, dsize, data);
00471 return;
00472
00473
00474 case 9:
00475 io_write(address + 0x3da, dsize, data);
00476 return;
00477 }
00478 }
00479
00483 u32 CCirrus::ReadMem_Bar(int func, int bar, u32 address, int dsize)
00484 {
00485 switch(bar)
00486 {
00487
00488 case 0:
00489 return mem_read(address, dsize);
00490 }
00491
00492 return 0;
00493 }
00494
00498 void CCirrus::WriteMem_Bar(int func, int bar, u32 address, int dsize, u32 data)
00499 {
00500 switch(bar)
00501 {
00502
00503 case 0:
00504 mem_write(address, dsize, data);
00505 return;
00506 }
00507 }
00508
00512 void CCirrus::check_state()
00513 {
00514 if(myThread && !myThread->isRunning())
00515 FAILURE(Thread, "Cirrus thread has died");
00516 }
00517
00518 static u32 cirrus_magic1 = 0xC1AA4500;
00519 static u32 cirrus_magic2 = 0x0054AA1C;
00520
00524 int CCirrus::SaveState(FILE* f)
00525 {
00526 long ss = sizeof(state);
00527 int res;
00528
00529 if(res = CPCIDevice::SaveState(f))
00530 return res;
00531
00532 fwrite(&cirrus_magic1, sizeof(u32), 1, f);
00533 fwrite(&ss, sizeof(long), 1, f);
00534 fwrite(&state, sizeof(state), 1, f);
00535 fwrite(&cirrus_magic2, sizeof(u32), 1, f);
00536 printf("%s: %d bytes saved.\n", devid_string, (int) ss);
00537 return 0;
00538 }
00539
00543 int CCirrus::RestoreState(FILE* f)
00544 {
00545 long ss;
00546 u32 m1;
00547 u32 m2;
00548 int res;
00549 size_t r;
00550
00551 if(res = CPCIDevice::RestoreState(f))
00552 return res;
00553
00554 r = fread(&m1, sizeof(u32), 1, f);
00555 if(r != 1)
00556 {
00557 printf("%s: unexpected end of file!\n", devid_string);
00558 return -1;
00559 }
00560
00561 if(m1 != cirrus_magic1)
00562 {
00563 printf("%s: MAGIC 1 does not match!\n", devid_string);
00564 return -1;
00565 }
00566
00567 fread(&ss, sizeof(long), 1, f);
00568 if(r != 1)
00569 {
00570 printf("%s: unexpected end of file!\n", devid_string);
00571 return -1;
00572 }
00573
00574 if(ss != sizeof(state))
00575 {
00576 printf("%s: STRUCT SIZE does not match!\n", devid_string);
00577 return -1;
00578 }
00579
00580 fread(&state, sizeof(state), 1, f);
00581 if(r != 1)
00582 {
00583 printf("%s: unexpected end of file!\n", devid_string);
00584 return -1;
00585 }
00586
00587 r = fread(&m2, sizeof(u32), 1, f);
00588 if(r != 1)
00589 {
00590 printf("%s: unexpected end of file!\n", devid_string);
00591 return -1;
00592 }
00593
00594 if(m2 != cirrus_magic2)
00595 {
00596 printf("%s: MAGIC 1 does not match!\n", devid_string);
00597 return -1;
00598 }
00599
00600 printf("%s: %d bytes restored.\n", devid_string, (int) ss);
00601 return 0;
00602 }
00603
00609 u32 CCirrus::mem_read(u32 address, int dsize)
00610 {
00611 u32 data = 0;
00612
00613
00614 return data;
00615 }
00616
00622 void CCirrus::mem_write(u32 address, int dsize, u32 data)
00623 {
00624
00625
00626 switch(dsize)
00627 {
00628 case 8:
00629 case 16:
00630 case 32:
00631 break;
00632 }
00633 }
00634
00640 u32 CCirrus::legacy_read(u32 address, int dsize)
00641 {
00642 u32 data = 0;
00643 switch(dsize)
00644 {
00645 case 32:
00646 data |= (u64) vga_mem_read((u32) address + 0xA0003) << 24;
00647 data |= (u64) vga_mem_read((u32) address + 0xA0002) << 16;
00648
00649 case 16:
00650 data |= (u64) vga_mem_read((u32) address + 0xA0001) << 8;
00651
00652 case 8:
00653 data |= (u64) vga_mem_read((u32) address + 0xA0000);
00654 }
00655
00656
00657 return data;
00658 }
00659
00665 void CCirrus::legacy_write(u32 address, int dsize, u32 data)
00666 {
00667
00668
00669 switch(dsize)
00670 {
00671 case 32:
00672 vga_mem_write((u32) address + 0xA0002, (u8) (data >> 16));
00673 vga_mem_write((u32) address + 0xA0003, (u8) (data >> 24));
00674
00675 case 16:
00676 vga_mem_write((u32) address + 0xA0001, (u8) (data >> 8));
00677
00678 case 8:
00679 vga_mem_write((u32) address + 0xA0000, (u8) (data));
00680 }
00681 }
00682
00686 u32 CCirrus::rom_read(u32 address, int dsize)
00687 {
00688 u32 data = 0x00;
00689 u8* x = (u8*) option_rom;
00690 if(address <= rom_max)
00691 {
00692 x += address;
00693 switch(dsize)
00694 {
00695 case 8: data = (u32) endian_8((*((u8*) x)) & 0xff); break;
00696 case 16: data = (u32) endian_16((*((u16*) x)) & 0xffff); break;
00697 case 32: data = (u32) endian_32((*((u32*) x)) & 0xffffffff); break;
00698 }
00699
00700
00701 }
00702 else
00703 {
00704 printf("cirrus: (BAD) rom read: %"LL "x, %d, %"LL "x\n", address, dsize,
00705 data);
00706 }
00707
00708 return data;
00709 }
00710
00714 u32 CCirrus::io_read(u32 address, int dsize)
00715 {
00716 u32 data = 0;
00717 if(dsize != 8)
00718 FAILURE(InvalidArgument, "Unsupported dsize!\n");
00719
00720 switch(address)
00721 {
00722 case 0x3c0:
00723 data = read_b_3c0();
00724 break;
00725
00726 case 0x3c1:
00727 data = read_b_3c1();
00728 break;
00729
00730 case 0x3c2:
00731 data = read_b_3c2();
00732 break;
00733
00734 case 0x3c3:
00735 data = read_b_3c3();
00736 break;
00737
00738 case 0x3c4:
00739 data = read_b_3c4();
00740 break;
00741
00742 case 0x3c5:
00743 data = read_b_3c5();
00744 break;
00745
00746 case 0x3c9:
00747 data = read_b_3c9();
00748 break;
00749
00750 case 0x3ca:
00751 data = read_b_3ca();
00752 break;
00753
00754 case 0x3cc:
00755 data = read_b_3cc();
00756 break;
00757
00758 case 0x3cf:
00759 data = read_b_3cf();
00760 break;
00761
00762 case 0x3b4:
00763 case 0x3d4:
00764 data = read_b_3d4();
00765 break;
00766
00767 case 0x3b5:
00768 case 0x3d5:
00769 data = read_b_3d5();
00770 break;
00771
00772 case 0x3ba:
00773 case 0x3da:
00774 data = read_b_3da();
00775 break;
00776
00777 default:
00778 FAILURE_1(NotImplemented, "Unhandled port %x read", address);
00779 }
00780
00781
00782 return data;
00783 }
00784
00790 void CCirrus::io_write(u32 address, int dsize, u32 data)
00791 {
00792
00793
00794 switch(dsize)
00795 {
00796 case 8:
00797 io_write_b(address, (u8) data);
00798 break;
00799
00800 case 16:
00801 io_write_b(address, (u8) data);
00802 io_write_b(address + 1, (u8) (data >> 8));
00803 break;
00804
00805 default:
00806 FAILURE(InvalidArgument, "Weird IO size!");
00807 }
00808 }
00809
00813 void CCirrus::io_write_b(u32 address, u8 data)
00814 {
00815 switch(address)
00816 {
00817 case 0x3c0:
00818 write_b_3c0(data);
00819 break;
00820
00821 case 0x3c2:
00822 write_b_3c2(data);
00823 break;
00824
00825 case 0x3c4:
00826 write_b_3c4(data);
00827 break;
00828
00829 case 0x3c5:
00830 write_b_3c5(data);
00831 break;
00832
00833 case 0x3c6:
00834 write_b_3c6(data);
00835 break;
00836
00837 case 0x3c7:
00838 write_b_3c7(data);
00839 break;
00840
00841 case 0x3c8:
00842 write_b_3c8(data);
00843 break;
00844
00845 case 0x3c9:
00846 write_b_3c9(data);
00847 break;
00848
00849 case 0x3ce:
00850 write_b_3ce(data);
00851 break;
00852
00853 case 0x3cf:
00854 write_b_3cf(data);
00855 break;
00856
00857 case 0x3b4:
00858 case 0x3d4:
00859 write_b_3d4(data);
00860 break;
00861
00862 case 0x3b5:
00863 case 0x3d5:
00864 write_b_3d5(data);
00865 break;
00866
00867 default:
00868 FAILURE_1(NotImplemented, "Unhandled port %x write", address);
00869 }
00870 }
00871
01002 void CCirrus::write_b_3c0(u8 value)
01003 {
01004
01005 bool prev_video_enabled;
01006 bool prev_line_graphics;
01007 bool prev_int_pal_size;
01008
01009
01010
01011 if(state.attribute_ctrl.flip_flop == 0)
01012 {
01013
01014
01015
01016
01017
01018
01019
01020 prev_video_enabled = state.attribute_ctrl.video_enabled;
01021 state.attribute_ctrl.video_enabled = (value >> 5) & 0x01;
01022 #if defined(DEBUG_VGA)
01023 printf("io write 3c0: video_enabled = %u \n",
01024 (unsigned) state.attribute_ctrl.video_enabled);
01025 #endif
01026 if(state.attribute_ctrl.video_enabled == 0)
01027 {
01028 if (prev_video_enabled)
01029 {
01030 #if defined(DEBUG_VGA)
01031 printf("found disable transition \n");
01032 #endif
01033
01034 bx_gui->lock();
01035 bx_gui->clear_screen();
01036 bx_gui->unlock();
01037 }
01038 }
01039 else if(!prev_video_enabled)
01040 {
01041 #if defined(DEBUG_VGA)
01042 printf("found enable transition \n");
01043 #endif
01044
01045 redraw_area(0, 0, old_iWidth, old_iHeight);
01046 }
01047
01048
01049 value &= 0x1f;
01050 state.attribute_ctrl.address = value;
01051
01052
01053
01054 #if defined(DEBUG_VGA)
01055 if (value>0x0f)
01056 printf("io write 3c0: address mode reg=%u \n", (unsigned) value);
01057 #endif
01058 }
01059 else
01060 {
01061
01062
01063
01064 if (state.attribute_ctrl.address<=0x0f)
01065 {
01066
01067 if(value != state.attribute_ctrl.palette_reg[state.attribute_ctrl.
01068 address])
01069 {
01070
01071 state.attribute_ctrl.palette_reg[state.attribute_ctrl.address] = value;
01072
01073 redraw_area(0, 0, old_iWidth, old_iHeight);
01074 }
01075 }
01076 else
01077 {
01078 switch(state.attribute_ctrl.address)
01079 {
01080
01081 case 0x10:
01082 prev_line_graphics = state.attribute_ctrl.mode_ctrl.enable_line_graphics;
01083 prev_int_pal_size = state.attribute_ctrl.mode_ctrl.internal_palette_size;
01084 state.attribute_ctrl.mode_ctrl.graphics_alpha = (value >> 0) & 0x01;
01085 state.attribute_ctrl.mode_ctrl.display_type = (value >> 1) & 0x01;
01086 state.attribute_ctrl.mode_ctrl.enable_line_graphics = (value >> 2) & 0x01;
01087 state.attribute_ctrl.mode_ctrl.blink_intensity = (value >> 3) & 0x01;
01088 state.attribute_ctrl.mode_ctrl.pixel_panning_compat = (value >> 5) & 0x01;
01089 state.attribute_ctrl.mode_ctrl.pixel_clock_select = (value >> 6) & 0x01;
01090 state.attribute_ctrl.mode_ctrl.internal_palette_size = (value >> 7) & 0x01;
01091 if(((value >> 2) & 0x01) != prev_line_graphics)
01092 {
01093 bx_gui->lock();
01094 bx_gui->set_text_charmap(&state.memory[0x20000 + state.charmap_address]);
01095 bx_gui->unlock();
01096 state.vga_mem_updated = 1;
01097 }
01098
01099 if(((value >> 7) & 0x01) != prev_int_pal_size)
01100 {
01101 redraw_area(0, 0, old_iWidth, old_iHeight);
01102 }
01103
01104 #if defined(DEBUG_VGA)
01105 printf("io write 3c0: mode control: %02x h \n", (unsigned) value);
01106 #endif
01107 break;
01108
01109
01110 case 0x11:
01111
01112
01113 state.attribute_ctrl.overscan_color = (value & 0x3f);
01114 #if defined(DEBUG_VGA)
01115 printf("io write 3c0: overscan color = %02x \n", (unsigned) value);
01116 #endif
01117 break;
01118
01119
01120 case 0x12:
01121 state.attribute_ctrl.color_plane_enable = (value & 0x0f);
01122 redraw_area(0, 0, old_iWidth, old_iHeight);
01123 #if defined(DEBUG_VGA)
01124 printf("io write 3c0: color plane enable = %02x \n", (unsigned) value);
01125 #endif
01126 break;
01127
01128
01129 case 0x13:
01130 state.attribute_ctrl.horiz_pel_panning = (value & 0x0f);
01131 redraw_area(0, 0, old_iWidth, old_iHeight);
01132 #if defined(DEBUG_VGA)
01133 printf("io write 3c0: horiz pel panning = %02x \n", (unsigned) value);
01134 #endif
01135 break;
01136
01137
01138 case 0x14:
01139 state.attribute_ctrl.color_select = (value & 0x0f);
01140 redraw_area(0, 0, old_iWidth, old_iHeight);
01141 #if defined(DEBUG_VGA)
01142 printf("io write 3c0: color select = %02x \n",
01143 (unsigned) state.attribute_ctrl.color_select);
01144 #endif
01145 break;
01146
01147 default:
01148 FAILURE_1(NotImplemented, "io write 3c0: data-write mode %02x h",
01149 (unsigned) state.attribute_ctrl.address);
01150 }
01151 }
01152 }
01153
01154
01155 state.attribute_ctrl.flip_flop = !state.attribute_ctrl.flip_flop;
01156 }
01157
01193 void CCirrus::write_b_3c2(u8 value)
01194 {
01195 state.misc_output.color_emulation = (value >> 0) & 0x01;
01196 state.misc_output.enable_ram = (value >> 1) & 0x01;
01197 state.misc_output.clock_select = (value >> 2) & 0x03;
01198 state.misc_output.select_high_bank = (value >> 5) & 0x01;
01199 state.misc_output.horiz_sync_pol = (value >> 6) & 0x01;
01200 state.misc_output.vert_sync_pol = (value >> 7) & 0x01;
01201 #if defined(DEBUG_VGA)
01202 printf("io write 3c2: \n");
01203 printf(" color_emulation = %u \n",
01204 (unsigned) state.misc_output.color_emulation);
01205 printf(" enable_ram = %u \n", (unsigned) state.misc_output.enable_ram);
01206 printf(" clock_select = %u \n", (unsigned) state.misc_output.clock_select);
01207 printf(" select_high_bank = %u \n",
01208 (unsigned) state.misc_output.select_high_bank);
01209 printf(" horiz_sync_pol = %u \n",
01210 (unsigned) state.misc_output.horiz_sync_pol);
01211 printf(" vert_sync_pol = %u \n", (unsigned) state.misc_output.vert_sync_pol);
01212 #endif
01213 }
01214
01357 void CCirrus::write_b_3c4(u8 value)
01358 {
01359 state.sequencer.index = value;
01360 }
01361
01367 void CCirrus::write_b_3c5(u8 value)
01368 {
01369 unsigned i;
01370 u8 charmap1;
01371 u8 charmap2;
01372
01373 switch(state.sequencer.index)
01374 {
01375
01376 case 0:
01377 #if defined(DEBUG_VGA)
01378 printf("write 0x3c5: sequencer reset: value=0x%02x \n", (unsigned) value);
01379 #endif
01380 if(state.sequencer.reset1 && ((value & 0x01) == 0))
01381 {
01382 state.sequencer.char_map_select = 0;
01383 state.charmap_address = 0;
01384 bx_gui->lock();
01385 bx_gui->set_text_charmap(&state.memory[0x20000 + state.charmap_address]);
01386 bx_gui->unlock();
01387 state.vga_mem_updated = 1;
01388 }
01389
01390 state.sequencer.reset1 = (value >> 0) & 0x01;
01391 state.sequencer.reset2 = (value >> 1) & 0x01;
01392 break;
01393
01394
01395 case 1:
01396 #if defined(DEBUG_VGA)
01397 printf("io write 3c5=%02x: clocking mode reg: ignoring \n",
01398 (unsigned) value);
01399 #endif
01400 state.sequencer.reg1 = value & 0x3f;
01401 state.x_dotclockdiv2 = ((value & 0x08) > 0);
01402 break;
01403
01404
01405 case 2:
01406 state.sequencer.map_mask = (value & 0x0f);
01407 for(i = 0; i < 4; i++)
01408 state.sequencer.map_mask_bit[i] = (value >> i) & 0x01;
01409 break;
01410
01411
01412 case 3:
01413 state.sequencer.char_map_select = value;
01414 charmap1 = value & 0x13;
01415 if(charmap1 > 3)
01416 charmap1 = (charmap1 & 3) + 4;
01417 charmap2 = (value & 0x2C) >> 2;
01418 if(charmap2 > 3)
01419 charmap2 = (charmap2 & 3) + 4;
01420 if(state.CRTC.reg[0x09] > 0)
01421 {
01422 state.charmap_address = (charmap1 << 13);
01423 bx_gui->lock();
01424 bx_gui->set_text_charmap(&state.memory[0x20000 + state.charmap_address]);
01425 bx_gui->unlock();
01426 state.vga_mem_updated = 1;
01427 }
01428
01429 if(charmap2 != charmap1)
01430 printf("char map select: #2=%d (unused) \n", charmap2);
01431 break;
01432
01433
01434 case 4:
01435 state.sequencer.extended_mem = (value >> 1) & 0x01;
01436 state.sequencer.odd_even = (value >> 2) & 0x01;
01437 state.sequencer.chain_four = (value >> 3) & 0x01;
01438
01439 #if defined(DEBUG_VGA)
01440 printf("io write 3c5: index 4: \n");
01441 printf(" extended_mem %u \n", (unsigned) state.sequencer.extended_mem);
01442 printf(" odd_even %u \n", (unsigned) state.sequencer.odd_even);
01443 printf(" chain_four %u \n", (unsigned) state.sequencer.chain_four);
01444 #endif
01445 break;
01446
01447 default:
01448 FAILURE_1(NotImplemented, "io write 3c5: index %u unhandled",
01449 (unsigned) state.sequencer.index);
01450 }
01451 }
01452
01459 void CCirrus::write_b_3c6(u8 value)
01460 {
01461 state.pel.mask = value;
01462 #if defined(DEBUG_VGA)
01463 if(state.pel.mask != 0xff)
01464 printf("io write 3c6: PEL mask=0x%02x != 0xFF \n", value);
01465 #endif
01466
01467
01468
01469 }
01470
01499 void CCirrus::write_b_3c7(u8 value)
01500 {
01501 state.pel.read_data_register = value;
01502 state.pel.read_data_cycle = 0;
01503 state.pel.dac_state = 0x03;
01504 }
01505
01511 void CCirrus::write_b_3c8(u8 value)
01512 {
01513 state.pel.write_data_register = value;
01514 state.pel.write_data_cycle = 0;
01515 state.pel.dac_state = 0x00;
01516 }
01517
01523 void CCirrus::write_b_3c9(u8 value)
01524 {
01525 switch(state.pel.write_data_cycle)
01526 {
01527 case 0:
01528 state.pel.data[state.pel.write_data_register].red = value;
01529 break;
01530
01531 case 1:
01532 state.pel.data[state.pel.write_data_register].green = value;
01533 break;
01534
01535 case 2:
01536 {
01537 state.pel.data[state.pel.write_data_register].blue = value;
01538
01539 bx_gui->lock();
01540 bool changed = bx_gui->palette_change(state.pel.write_data_register,
01541 state.pel.data[state.pel.write_data_register].red << 2,
01542 state.pel.data[state.pel.write_data_register].green << 2,
01543 state.pel.data[state.pel.write_data_register].blue << 2);
01544 bx_gui->unlock();
01545
01546 if(changed)
01547 redraw_area(0, 0, old_iWidth, old_iHeight);
01548 }
01549 break;
01550 }
01551
01552
01553 state.pel.write_data_cycle++;
01554
01555
01556 if(state.pel.write_data_cycle >= 3)
01557 {
01558
01559
01560
01561
01562
01563
01564 state.pel.write_data_cycle = 0;
01565 state.pel.write_data_register++;
01566 }
01567 }
01568
01801 void CCirrus::write_b_3ce(u8 value)
01802 {
01803 #if defined(DEBUG_VGA)
01804 if(value > 0x08)
01805 printf("io write: 3ce: value > 8 \n");
01806 #endif
01807 state.graphics_ctrl.index = value;
01808 }
01809
01815 void CCirrus::write_b_3cf(u8 value)
01816 {
01817 u8 prev_memory_mapping;
01818 bool prev_graphics_alpha;
01819 bool prev_chain_odd_even;
01820
01821
01822 switch(state.graphics_ctrl.index)
01823 {
01824 case 0:
01825 state.graphics_ctrl.set_reset = value & 0x0f;
01826 break;
01827
01828 case 1:
01829 state.graphics_ctrl.enable_set_reset = value & 0x0f;
01830 break;
01831
01832 case 2:
01833 state.graphics_ctrl.color_compare = value & 0x0f;
01834 break;
01835
01836 case 3:
01837 state.graphics_ctrl.data_rotate = value & 0x07;
01838
01839
01840 state.graphics_ctrl.raster_op = (value >> 3) & 0x03;
01841 break;
01842
01843 case 4:
01844 state.graphics_ctrl.read_map_select = value & 0x03;
01845 #if defined(DEBUG_VGA)
01846 printf("io write to 03cf = %02x (RMS) \n", (unsigned) value);
01847 #endif
01848 break;
01849
01850 case 5:
01851 state.graphics_ctrl.write_mode = value & 0x03;
01852 state.graphics_ctrl.read_mode = (value >> 3) & 0x01;
01853 state.graphics_ctrl.odd_even = (value >> 4) & 0x01;
01854 state.graphics_ctrl.shift_reg = (value >> 5) & 0x03;
01855
01856 #if defined(DEBUG_VGA)
01857 if(state.graphics_ctrl.odd_even)
01858 printf("io write: 3cf: reg 05: value = %02xh \n", (unsigned) value);
01859 if(state.graphics_ctrl.shift_reg)
01860 printf("io write: 3cf: reg 05: value = %02xh \n", (unsigned) value);
01861 #endif
01862 break;
01863
01864 case 6:
01865 prev_graphics_alpha = state.graphics_ctrl.graphics_alpha;
01866 prev_chain_odd_even = state.graphics_ctrl.chain_odd_even;
01867 prev_memory_mapping = state.graphics_ctrl.memory_mapping;
01868
01869 state.graphics_ctrl.graphics_alpha = value & 0x01;
01870 state.graphics_ctrl.chain_odd_even = (value >> 1) & 0x01;
01871 state.graphics_ctrl.memory_mapping = (value >> 2) & 0x03;
01872 #if defined(DEBUG_VGA)
01873 printf("memory_mapping set to %u \n",
01874 (unsigned) state.graphics_ctrl.memory_mapping);
01875 printf("graphics mode set to %u \n",
01876 (unsigned) state.graphics_ctrl.graphics_alpha);
01877 printf("odd_even mode set to %u \n",
01878 (unsigned) state.graphics_ctrl.odd_even);
01879 printf("io write: 3cf: reg 06: value = %02xh \n", (unsigned) value);
01880 #endif
01881 if(prev_memory_mapping != state.graphics_ctrl.memory_mapping)
01882 {
01883 redraw_area(0, 0, old_iWidth, old_iHeight);
01884 }
01885
01886 if(prev_graphics_alpha != state.graphics_ctrl.graphics_alpha)
01887 {
01888 redraw_area(0, 0, old_iWidth, old_iHeight);
01889 old_iHeight = 0;
01890 }
01891 break;
01892
01893 case 7:
01894 state.graphics_ctrl.color_dont_care = value & 0x0f;
01895 break;
01896
01897 case 8:
01898 state.graphics_ctrl.bitmask = value;
01899 break;
01900
01901 default:
01902
01903
01904 FAILURE_1(NotImplemented, "io write: 3cf: index %u unhandled",
01905 (unsigned) state.graphics_ctrl.index);
01906 }
01907 }
01908
02431 void CCirrus::write_b_3d4(u8 value)
02432 {
02433 state.CRTC.address = value & 0x7f;
02434 #if defined(DEBUG_VGA)
02435 if(state.CRTC.address > 0x18)
02436 printf("write: invalid CRTC register 0x%02x selected",
02437 (unsigned) state.CRTC.address);
02438 #endif
02439 }
02440
02446 void CCirrus::write_b_3d5(u8 value)
02447 {
02448
02449
02450 if(state.CRTC.address > 0x18)
02451 {
02452 #if defined(DEBUG_VGA)
02453 printf("write: invalid CRTC register 0x%02x ignored",
02454 (unsigned) state.CRTC.address);
02455 #endif
02456 return;
02457 }
02458
02459 if(state.CRTC.write_protect && (state.CRTC.address < 0x08))
02460 {
02461 if(state.CRTC.address == 0x07)
02462 {
02463 state.CRTC.reg[state.CRTC.address] &= ~0x10;
02464 state.CRTC.reg[state.CRTC.address] |= (value & 0x10);
02465 state.line_compare &= 0x2ff;
02466 if(state.CRTC.reg[0x07] & 0x10)
02467 state.line_compare |= 0x100;
02468 redraw_area(0, 0, old_iWidth, old_iHeight);
02469 return;
02470 }
02471 else
02472 {
02473 return;
02474 }
02475 }
02476
02477 if(value != state.CRTC.reg[state.CRTC.address])
02478 {
02479 state.CRTC.reg[state.CRTC.address] = value;
02480 switch(state.CRTC.address)
02481 {
02482 case 0x07:
02483 state.vertical_display_end &= 0xff;
02484 if(state.CRTC.reg[0x07] & 0x02)
02485 state.vertical_display_end |= 0x100;
02486 if(state.CRTC.reg[0x07] & 0x40)
02487 state.vertical_display_end |= 0x200;
02488 state.line_compare &= 0x2ff;
02489 if(state.CRTC.reg[0x07] & 0x10)
02490 state.line_compare |= 0x100;
02491 redraw_area(0, 0, old_iWidth, old_iHeight);
02492 break;
02493
02494 case 0x08:
02495
02496
02497 redraw_area(0, 0, old_iWidth, old_iHeight);
02498 break;
02499
02500 case 0x09:
02501 state.y_doublescan = ((value & 0x9f) > 0);
02502 state.line_compare &= 0x1ff;
02503 if(state.CRTC.reg[0x09] & 0x40)
02504 state.line_compare |= 0x200;
02505 redraw_area(0, 0, old_iWidth, old_iHeight);
02506 break;
02507
02508 case 0x0A:
02509 case 0x0B:
02510 case 0x0E:
02511 case 0x0F:
02512
02513
02514 state.vga_mem_updated = 1;
02515 break;
02516
02517 case 0x0C:
02518 case 0x0D:
02519
02520
02521 if(state.graphics_ctrl.graphics_alpha)
02522 {
02523 redraw_area(0, 0, old_iWidth, old_iHeight);
02524 }
02525 else
02526 {
02527 state.vga_mem_updated = 1;
02528 }
02529 break;
02530
02531 case 0x12:
02532 state.vertical_display_end &= 0x300;
02533 state.vertical_display_end |= state.CRTC.reg[0x12];
02534 break;
02535
02536 case 0x13:
02537 case 0x14:
02538 case 0x17:
02539
02540
02541 state.line_offset = state.CRTC.reg[0x13] << 1;
02542 if(state.CRTC.reg[0x14] & 0x40)
02543 state.line_offset <<= 2;
02544 else if((state.CRTC.reg[0x17] & 0x40) == 0)
02545 state.line_offset <<= 1;
02546 redraw_area(0, 0, old_iWidth, old_iHeight);
02547 break;
02548
02549 case 0x18:
02550 state.line_compare &= 0x300;
02551 state.line_compare |= state.CRTC.reg[0x18];
02552 redraw_area(0, 0, old_iWidth, old_iHeight);
02553 break;
02554 }
02555 }
02556 }
02557
02563 u8 CCirrus::read_b_3c0()
02564 {
02565 if(state.attribute_ctrl.flip_flop == 0)
02566 {
02567
02568
02569 return(state.attribute_ctrl.video_enabled << 5) | state.attribute_ctrl.address;
02570 }
02571 else
02572 {
02573 FAILURE(NotImplemented, "io read: 0x3c0: flip_flop != 0");
02574 }
02575 }
02576
02582 u8 CCirrus::read_b_3c1()
02583 {
02584 u8 retval;
02585 switch(state.attribute_ctrl.address)
02586 {
02587 case 0x00:
02588 case 0x01:
02589 case 0x02:
02590 case 0x03:
02591 case 0x04:
02592 case 0x05:
02593 case 0x06:
02594 case 0x07:
02595 case 0x08:
02596 case 0x09:
02597 case 0x0a:
02598 case 0x0b:
02599 case 0x0c:
02600 case 0x0d:
02601 case 0x0e:
02602 case 0x0f:
02603 retval = state.attribute_ctrl.palette_reg[state.attribute_ctrl.address];
02604 return(retval);
02605 break;
02606
02607 case 0x10:
02608 retval = (state.attribute_ctrl.mode_ctrl.graphics_alpha << 0) |
02609 (state.attribute_ctrl.mode_ctrl.display_type << 1) |
02610 (state.attribute_ctrl.mode_ctrl.enable_line_graphics << 2) |
02611 (state.attribute_ctrl.mode_ctrl.blink_intensity << 3) |
02612 (state.attribute_ctrl.mode_ctrl.pixel_panning_compat << 5) |
02613 (state.attribute_ctrl.mode_ctrl.pixel_clock_select << 6) |
02614 (state.attribute_ctrl.mode_ctrl.internal_palette_size << 7);
02615 return(retval);
02616 break;
02617
02618 case 0x11:
02619 return(state.attribute_ctrl.overscan_color);
02620 break;
02621
02622 case 0x12:
02623 return(state.attribute_ctrl.color_plane_enable);
02624 break;
02625
02626 case 0x13:
02627 return(state.attribute_ctrl.horiz_pel_panning);
02628 break;
02629
02630 case 0x14:
02631 return(state.attribute_ctrl.color_select);
02632 break;
02633
02634 default:
02635 FAILURE_1(NotImplemented, "io read: 0x3c1: unknown register 0x%02x",
02636 (unsigned) state.attribute_ctrl.address);
02637 }
02638 }
02639
02654 u8 CCirrus::read_b_3c2()
02655 {
02656 return 0;
02657 }
02658
02664 u8 CCirrus::read_b_3c3()
02665 {
02666 return state.vga_enabled;
02667 }
02668
02674 u8 CCirrus::read_b_3c4()
02675 {
02676 return state.sequencer.index;
02677 }
02678
02684 u8 CCirrus::read_b_3c5()
02685 {
02686 switch(state.sequencer.index)
02687 {
02688 case 0:
02689 #if defined(DEBUG_VGA)
02690 BX_DEBUG(("io read 0x3c5: sequencer reset"));
02691 #endif
02692 return(state.sequencer.reset1 ? 1 : 0) | (state.sequencer.reset2 ? 2 : 0);
02693 break;
02694
02695 case 1:
02696 #if defined(DEBUG_VGA)
02697 BX_DEBUG(("io read 0x3c5: sequencer clocking mode"));
02698 #endif
02699 return state.sequencer.reg1;
02700 break;
02701
02702 case 2:
02703 return state.sequencer.map_mask;
02704 break;
02705
02706 case 3:
02707 return state.sequencer.char_map_select;
02708 break;
02709
02710 case 4:
02711 return(state.sequencer.extended_mem << 1) |
02712 (state.sequencer.odd_even << 2) |
02713 (state.sequencer.chain_four << 3);
02714 break;
02715
02716 default:
02717 FAILURE_1(NotImplemented, "io read 0x3c5: index %u unhandled",
02718 (unsigned) state.sequencer.index);
02719 }
02720 }
02721
02727 u8 CCirrus::read_b_3c9()
02728 {
02729 u8 retval;
02730 if(state.pel.dac_state == 0x03)
02731 {
02732 switch(state.pel.read_data_cycle)
02733 {
02734 case 0: retval = state.pel.data[state.pel.read_data_register].red; break;
02735 case 1: retval = state.pel.data[state.pel.read_data_register].green; break;
02736 case 2: retval = state.pel.data[state.pel.read_data_register].blue; break;
02737 default: retval = 0;
02738 }
02739
02740 state.pel.read_data_cycle++;
02741 if(state.pel.read_data_cycle >= 3)
02742 {
02743 state.pel.read_data_cycle = 0;
02744 state.pel.read_data_register++;
02745 }
02746 }
02747 else
02748 {
02749 retval = 0x3f;
02750 }
02751
02752 return retval;
02753 }
02766 u8 CCirrus::read_b_3ca()
02767 {
02768 return 0;
02769 }
02770
02776 u8 CCirrus::read_b_3cc()
02777 {
02778
02779
02780 return((state.misc_output.color_emulation & 0x01) << 0) |
02781 ((state.misc_output.enable_ram & 0x01) << 1) |
02782 ((state.misc_output.clock_select & 0x03) << 2) |
02783 ((state.misc_output.select_high_bank & 0x01) << 5) |
02784 ((state.misc_output.horiz_sync_pol & 0x01) << 6) |
02785 ((state.misc_output.vert_sync_pol & 0x01) << 7);
02786 }
02787
02793 u8 CCirrus::read_b_3cf()
02794 {
02795 u8 retval;
02796 switch(state.graphics_ctrl.index)
02797 {
02798 case 0:
02799 return(state.graphics_ctrl.set_reset);
02800 break;
02801
02802 case 1:
02803 return(state.graphics_ctrl.enable_set_reset);
02804 break;
02805
02806 case 2:
02807 return(state.graphics_ctrl.color_compare);
02808 break;
02809
02810 case 3:
02811 retval = ((state.graphics_ctrl.raster_op & 0x03) << 3) | ((state.graphics_ctrl.data_rotate & 0x07) << 0);
02812 return(retval);
02813 break;
02814
02815 case 4:
02816 return(state.graphics_ctrl.read_map_select);
02817 break;
02818
02819 case 5:
02820 retval = ((state.graphics_ctrl.shift_reg & 0x03) << 5) |
02821 ((state.graphics_ctrl.odd_even & 0x01) << 4) |
02822 ((state.graphics_ctrl.read_mode & 0x01) << 3) |
02823 ((state.graphics_ctrl.write_mode & 0x03) << 0);
02824
02825 #if defined(DEBUG_VGA)
02826 if(state.graphics_ctrl.odd_even || state.graphics_ctrl.shift_reg)
02827 BX_DEBUG(("io read 0x3cf: reg 05 = 0x%02x", (unsigned) retval));
02828 #endif
02829 return(retval);
02830 break;
02831
02832 case 6:
02833 return((state.graphics_ctrl.memory_mapping & 0x03) << 2) |
02834 ((state.graphics_ctrl.odd_even & 0x01) << 1) |
02835 ((state.graphics_ctrl.graphics_alpha & 0x01) << 0);
02836 break;
02837
02838 case 7:
02839 return(state.graphics_ctrl.color_dont_care);
02840 break;
02841
02842 case 8:
02843 return(state.graphics_ctrl.bitmask);
02844 break;
02845
02846 default:
02847 FAILURE_1(NotImplemented, "io read: 0x3cf: index %u unhandled",
02848 (unsigned) state.graphics_ctrl.index);
02849 }
02850 }
02851
02857 u8 CCirrus::read_b_3d4()
02858 {
02859 return state.CRTC.address;
02860 }
02861
02867 u8 CCirrus::read_b_3d5()
02868 {
02869 if(state.CRTC.address > 0x18)
02870 {
02871 FAILURE_1(NotImplemented, "io read: invalid CRTC register 0x%02x \n",
02872 (unsigned) state.CRTC.address);
02873 }
02874
02875 return state.CRTC.reg[state.CRTC.address];
02876 }
02877
02901 u8 CCirrus::read_b_3da()
02902 {
02903
02904
02905 u8 retval = 0;
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940 state.attribute_ctrl.flip_flop = 0;
02941 return retval;
02942 }
02943
02944 u8 CCirrus::get_actl_palette_idx(u8 index)
02945 {
02946 return state.attribute_ctrl.palette_reg[index];
02947 }
02948
02949 void CCirrus::redraw_area(unsigned x0, unsigned y0, unsigned width,
02950 unsigned height)
02951 {
02952 unsigned xti;
02953
02954 unsigned yti;
02955
02956 unsigned xt0;
02957
02958 unsigned xt1;
02959
02960 unsigned yt0;
02961
02962 unsigned yt1;
02963
02964 unsigned xmax;
02965
02966 unsigned ymax;
02967
02968 if((width == 0) || (height == 0))
02969 {
02970 return;
02971 }
02972
02973 state.vga_mem_updated = 1;
02974
02975 if(state.graphics_ctrl.graphics_alpha)
02976 {
02977
02978
02979 xmax = old_iWidth;
02980 ymax = old_iHeight;
02981 xt0 = x0 / X_TILESIZE;
02982 yt0 = y0 / Y_TILESIZE;
02983 if(x0 < xmax)
02984 {
02985 xt1 = (x0 + width - 1) / X_TILESIZE;
02986 }
02987 else
02988 {
02989 xt1 = (xmax - 1) / X_TILESIZE;
02990 }
02991
02992 if(y0 < ymax)
02993 {
02994 yt1 = (y0 + height - 1) / Y_TILESIZE;
02995 }
02996 else
02997 {
02998 yt1 = (ymax - 1) / Y_TILESIZE;
02999 }
03000
03001 for(yti = yt0; yti <= yt1; yti++)
03002 {
03003 for(xti = xt0; xti <= xt1; xti++)
03004 {
03005 SET_TILE_UPDATED(xti, yti, 1);
03006 }
03007 }
03008 }
03009 else
03010 {
03011
03012
03013 memset(state.text_snapshot, 0, sizeof(state.text_snapshot));
03014 }
03015 }
03016
03017 void CCirrus::update(void)
03018 {
03019 unsigned iHeight;
03020
03021 unsigned iWidth;
03022
03023
03024 if(state.vga_mem_updated == 0)
03025 return;
03026
03027
03028 if(!state.vga_enabled || !state.attribute_ctrl.video_enabled
03029 || !state.sequencer.reset2 || !state.sequencer.reset1) return;
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041 if(state.graphics_ctrl.graphics_alpha)
03042 {
03043 u8 color;
03044 unsigned bit_no;
03045 unsigned r;
03046 unsigned c;
03047 unsigned x;
03048 unsigned y;
03049 unsigned long byte_offset;
03050 unsigned long start_addr;
03051 unsigned xc;
03052 unsigned yc;
03053 unsigned xti;
03054 unsigned yti;
03055
03056 start_addr = (state.CRTC.reg[0x0c] << 8) | state.CRTC.reg[0x0d];
03057
03058
03059
03060
03061
03062 determine_screen_dimensions(&iHeight, &iWidth);
03063 if((iWidth != old_iWidth) || (iHeight != old_iHeight) || (state.last_bpp > 8))
03064 {
03065 bx_gui->dimension_update(iWidth, iHeight);
03066 old_iWidth = iWidth;
03067 old_iHeight = iHeight;
03068 state.last_bpp = 8;
03069 }
03070
03071 switch(state.graphics_ctrl.shift_reg)
03072 {
03073 case 0:
03074 u8 attribute, palette_reg_val, DAC_regno;
03075
03076 unsigned long line_compare;
03077 u8* plane0;
03078 u8 *plane1;
03079 u8 *plane2;
03080 u8 *plane3;
03081
03082 if(state.graphics_ctrl.memory_mapping == 3)
03083 {
03084 for(yc = 0, yti = 0; yc < iHeight; yc += Y_TILESIZE, yti++)
03085 {
03086 for(xc = 0, xti = 0; xc < iWidth; xc += X_TILESIZE, xti++)
03087 {
03088 if(GET_TILE_UPDATED(xti, yti))
03089 {
03090 for(r = 0; r < Y_TILESIZE; r++)
03091 {
03092 y = yc + r;
03093 if(state.y_doublescan)
03094 y >>= 1;
03095 for(c = 0; c < X_TILESIZE; c++)
03096 {
03097 x = xc + c;
03098
03099
03100 byte_offset = start_addr + ((y & 1) << 13);
03101
03102
03103 byte_offset += (320 / 4) * (y / 2);
03104
03105
03106 byte_offset += (x / 8);
03107
03108 bit_no = 7 - (x % 8);
03109 palette_reg_val = (((state.memory[byte_offset]) >> bit_no) & 1);
03110 DAC_regno = state.attribute_ctrl.palette_reg[palette_reg_val];
03111 state.tile[r * X_TILESIZE + c] = DAC_regno;
03112 }
03113 }
03114
03115 SET_TILE_UPDATED(xti, yti, 0);
03116 bx_gui->graphics_tile_update(state.tile, xc, yc);
03117 }
03118 }
03119 }
03120 }
03121 else
03122 {
03123
03124 plane0 = &state.memory[0 << 16];
03125 plane1 = &state.memory[1 << 16];
03126 plane2 = &state.memory[2 << 16];
03127 plane3 = &state.memory[3 << 16];
03128 line_compare = state.line_compare;
03129 if(state.y_doublescan)
03130 line_compare >>= 1;
03131
03132 for(yc = 0, yti = 0; yc < iHeight; yc += Y_TILESIZE, yti++)
03133 {
03134 for(xc = 0, xti = 0; xc < iWidth; xc += X_TILESIZE, xti++)
03135 {
03136 if(GET_TILE_UPDATED(xti, yti))
03137 {
03138 for(r = 0; r < Y_TILESIZE; r++)
03139 {
03140 y = yc + r;
03141 if(state.y_doublescan)
03142 y >>= 1;
03143 for(c = 0; c < X_TILESIZE; c++)
03144 {
03145 x = xc + c;
03146 if(state.x_dotclockdiv2)
03147 x >>= 1;
03148 bit_no = 7 - (x % 8);
03149 if(y > line_compare)
03150 {
03151 byte_offset = x / 8 + ((y - line_compare - 1) * state.line_offset);
03152 }
03153 else
03154 {
03155 byte_offset = start_addr + x / 8 + (y * state.line_offset);
03156 }
03157
03158 attribute = (((plane0[byte_offset] >> bit_no) & 0x01) << 0) |
03159 (((plane1[byte_offset] >> bit_no) & 0x01) << 1) |
03160 (((plane2[byte_offset] >> bit_no) & 0x01) << 2) |
03161 (((plane3[byte_offset] >> bit_no) & 0x01) << 3);
03162
03163 attribute &= state.attribute_ctrl.color_plane_enable;
03164
03165
03166
03167 if(state.attribute_ctrl.mode_ctrl.blink_intensity)
03168 attribute ^= 0x08;
03169 palette_reg_val = state.attribute_ctrl.palette_reg[attribute];
03170 if(state.attribute_ctrl.mode_ctrl.internal_palette_size)
03171 {
03172
03173
03174
03175
03176 DAC_regno = (palette_reg_val & 0x0f) | (state.attribute_ctrl.color_select << 4);
03177 }
03178 else
03179 {
03180
03181
03182
03183
03184 DAC_regno = (palette_reg_val & 0x3f) | ((state.attribute_ctrl.color_select & 0x0c) << 4);
03185 }
03186
03187
03188 state.tile[r * X_TILESIZE + c] = DAC_regno;
03189 }
03190 }
03191
03192 SET_TILE_UPDATED(xti, yti, 0);
03193 bx_gui->graphics_tile_update(state.tile, xc, yc);
03194 }
03195 }
03196 }
03197 }
03198 break;
03199
03200 case 1:
03201
03202
03203
03204 for(yc = 0, yti = 0; yc < iHeight; yc += Y_TILESIZE, yti++)
03205 {
03206 for(xc = 0, xti = 0; xc < iWidth; xc += X_TILESIZE, xti++)
03207 {
03208 if(GET_TILE_UPDATED(xti, yti))
03209 {
03210 for(r = 0; r < Y_TILESIZE; r++)
03211 {
03212 y = yc + r;
03213 if(state.y_doublescan)
03214 y >>= 1;
03215 for(c = 0; c < X_TILESIZE; c++)
03216 {
03217 x = xc + c;
03218 if(state.x_dotclockdiv2)
03219 x >>= 1;
03220
03221
03222 byte_offset = start_addr + ((y & 1) << 13);
03223
03224
03225 byte_offset += (320 / 4) * (y / 2);
03226
03227
03228 byte_offset += (x / 4);
03229
03230 attribute = 6 - 2 * (x % 4);
03231 palette_reg_val = (state.memory[byte_offset]) >> attribute;
03232 palette_reg_val &= 3;
03233 DAC_regno = state.attribute_ctrl.palette_reg[palette_reg_val];
03234 state.tile[r * X_TILESIZE + c] = DAC_regno;
03235 }
03236 }
03237
03238 SET_TILE_UPDATED(xti, yti, 0);
03239 bx_gui->graphics_tile_update(state.tile, xc, yc);
03240 }
03241 }
03242 }
03243
03244
03245 break;
03246
03247 case 2:
03248
03249
03250 case 3:
03251 if(state.sequencer.chain_four)
03252 {
03253 unsigned long pixely;
03254
03255 unsigned long pixelx;
03256
03257 unsigned long plane;
03258
03259 if(state.misc_output.select_high_bank != 1)
03260 {
03261 FAILURE(NotImplemented, "update: select_high_bank != 1 \n");
03262 }
03263
03264 for(yc = 0, yti = 0; yc < iHeight; yc += Y_TILESIZE, yti++)
03265 {
03266 for(xc = 0, xti = 0; xc < iWidth; xc += X_TILESIZE, xti++)
03267 {
03268 if(GET_TILE_UPDATED(xti, yti))
03269 {
03270 for(r = 0; r < Y_TILESIZE; r++)
03271 {
03272 pixely = yc + r;
03273 if(state.y_doublescan)
03274 pixely >>= 1;
03275 for(c = 0; c < X_TILESIZE; c++)
03276 {
03277 pixelx = (xc + c) >> 1;
03278 plane = (pixelx % 4);
03279 byte_offset = start_addr + (plane * 65536) + (pixely * state.line_offset) + (pixelx &~0x03);
03280 color = state.memory[byte_offset];
03281 state.tile[r * X_TILESIZE + c] = color;
03282 }
03283 }
03284
03285 SET_TILE_UPDATED(xti, yti, 0);
03286 bx_gui->graphics_tile_update(state.tile, xc, yc);
03287 }
03288 }
03289 }
03290 }
03291 else
03292 {
03293 unsigned long pixely;
03294
03295
03296 unsigned long pixelx;
03297
03298
03299 unsigned long plane;
03300
03301 for(yc = 0, yti = 0; yc < iHeight; yc += Y_TILESIZE, yti++)
03302 {
03303 for(xc = 0, xti = 0; xc < iWidth; xc += X_TILESIZE, xti++)
03304 {
03305 if(GET_TILE_UPDATED(xti, yti))
03306 {
03307 for(r = 0; r < Y_TILESIZE; r++)
03308 {
03309 pixely = yc + r;
03310 if(state.y_doublescan)
03311 pixely >>= 1;
03312 for(c = 0; c < X_TILESIZE; c++)
03313 {
03314 pixelx = (xc + c) >> 1;
03315 plane = (pixelx % 4);
03316 byte_offset = (plane * 65536) + (pixely * state.line_offset) + (pixelx >> 2);
03317 color = state.memory[start_addr + byte_offset];
03318 state.tile[r * X_TILESIZE + c] = color;
03319 }
03320 }
03321
03322 SET_TILE_UPDATED(xti, yti, 0);
03323 bx_gui->graphics_tile_update(state.tile, xc, yc);
03324 }
03325 }
03326 }
03327 }
03328 break;
03329
03330 default:
03331 FAILURE_1(NotImplemented, "update: shift_reg == %u \n",
03332 (unsigned) state.graphics_ctrl.shift_reg);
03333 }
03334
03335 state.vga_mem_updated = 0;
03336 return;
03337 }
03338 else
03339 {
03340 unsigned long start_address;
03341 unsigned long cursor_address;
03342 unsigned long cursor_x;
03343 unsigned long cursor_y;
03344 bx_vga_tminfo_t tm_info;
03345 unsigned VDE;
03346 unsigned MSL;
03347 unsigned cols;
03348 unsigned rows;
03349 unsigned cWidth;
03350
03351 tm_info.start_address = 2 * ((state.CRTC.reg[12] << 8) + state.CRTC.reg[13]);
03352 tm_info.cs_start = state.CRTC.reg[0x0a] & 0x3f;
03353 tm_info.cs_end = state.CRTC.reg[0x0b] & 0x1f;
03354 tm_info.line_offset = state.CRTC.reg[0x13] << 2;
03355 tm_info.line_compare = state.line_compare;
03356 tm_info.h_panning = state.attribute_ctrl.horiz_pel_panning & 0x0f;
03357 tm_info.v_panning = state.CRTC.reg[0x08] & 0x1f;
03358 tm_info.line_graphics = state.attribute_ctrl.mode_ctrl.enable_line_graphics;
03359 tm_info.split_hpanning = state.attribute_ctrl.mode_ctrl.pixel_panning_compat;
03360 if((state.sequencer.reg1 & 0x01) == 0)
03361 {
03362 if(tm_info.h_panning >= 8)
03363 tm_info.h_panning = 0;
03364 else
03365 tm_info.h_panning++;
03366 }
03367 else
03368 {
03369 tm_info.h_panning &= 0x07;
03370 }
03371
03372
03373 VDE = state.vertical_display_end;
03374
03375
03376 MSL = state.CRTC.reg[0x09] & 0x1f;
03377 if(MSL == 0)
03378 {
03379 #if defined(DEBUG_VGA)
03380 BX_ERROR(("character height = 1, skipping text update"));
03381 #endif
03382 return;
03383 }
03384
03385 cols = state.CRTC.reg[1] + 1;
03386 if((MSL == 1) && (VDE == 399))
03387 {
03388
03389
03390 MSL = 3;
03391 }
03392
03393 rows = (VDE + 1) / (MSL + 1);
03394 if(rows > BX_MAX_TEXT_LINES)
03395 {
03396 BX_PANIC(("text rows>%d: %d", BX_MAX_TEXT_LINES, rows));
03397 return;
03398 }
03399
03400 cWidth = ((state.sequencer.reg1 & 0x01) == 1) ? 8 : 9;
03401 iWidth = cWidth * cols;
03402 iHeight = VDE + 1;
03403 if((iWidth != old_iWidth) || (iHeight != old_iHeight) || (MSL != old_MSL)
03404 || (state.last_bpp > 8))
03405 {
03406 bx_gui->dimension_update(iWidth, iHeight, MSL + 1, cWidth);
03407 old_iWidth = iWidth;
03408 old_iHeight = iHeight;
03409 old_MSL = MSL;
03410 state.last_bpp = 8;
03411 }
03412
03413
03414 start_address = 2 * ((state.CRTC.reg[12] << 8) + state.CRTC.reg[13]);
03415 cursor_address = 2 * ((state.CRTC.reg[0x0e] << 8) + state.CRTC.reg[0x0f]);
03416 if(cursor_address < start_address)
03417 {
03418 cursor_x = 0xffff;
03419 cursor_y = 0xffff;
03420 }
03421 else
03422 {
03423 cursor_x = ((cursor_address - start_address) / 2) % (iWidth / cWidth);
03424 cursor_y = ((cursor_address - start_address) / 2) / (iWidth / cWidth);
03425 }
03426
03427 bx_gui->text_update(state.text_snapshot, &state.memory[start_address],
03428 cursor_x, cursor_y, tm_info, rows);
03429
03430
03431 memcpy(state.text_snapshot, &state.memory[start_address], 2 * cols * rows);
03432 state.vga_mem_updated = 0;
03433 }
03434 }
03435
03436 void CCirrus::determine_screen_dimensions(unsigned* piHeight, unsigned* piWidth)
03437 {
03438 int ai[0x20];
03439 int i;
03440 int h;
03441 int v;
03442 for(i = 0; i < 0x20; i++)
03443 ai[i] = state.CRTC.reg[i];
03444
03445 h = (ai[1] + 1) * 8;
03446 v = (ai[18] | ((ai[7] & 0x02) << 7) | ((ai[7] & 0x40) << 3)) + 1;
03447
03448 if(state.graphics_ctrl.shift_reg == 0)
03449 {
03450 *piWidth = 640;
03451 *piHeight = 480;
03452
03453 if(state.CRTC.reg[6] == 0xBF)
03454 {
03455 if(state.CRTC.reg[23] == 0xA3 && state.CRTC.reg[20] == 0x40
03456 && state.CRTC.reg[9] == 0x41)
03457 {
03458 *piWidth = 320;
03459 *piHeight = 240;
03460 }
03461 else
03462 {
03463 if(state.x_dotclockdiv2)
03464 h <<= 1;
03465 *piWidth = h;
03466 *piHeight = v;
03467 }
03468 }
03469 else if((h >= 640) && (v >= 480))
03470 {
03471 *piWidth = h;
03472 *piHeight = v;
03473 }
03474 }
03475 else if(state.graphics_ctrl.shift_reg == 2)
03476 {
03477 if(state.sequencer.chain_four)
03478 {
03479 *piWidth = h;
03480 *piHeight = v;
03481 }
03482 else
03483 {
03484 *piWidth = h;
03485 *piHeight = v;
03486 }
03487 }
03488 else
03489 {
03490 if(state.x_dotclockdiv2)
03491 h <<= 1;
03492 *piWidth = h;
03493 *piHeight = v;
03494 }
03495 }
03496
03497 u8 CCirrus::vga_mem_read(u32 addr)
03498 {
03499 u32 offset;
03500 u8* plane0;
03501 u8 *plane1;
03502 u8 *plane2;
03503 u8 *plane3;
03504 u8 retval = 0;
03505
03506 switch(state.graphics_ctrl.memory_mapping)
03507 {
03508 case 1:
03509 if(addr > 0xAFFFF)
03510 return 0xff;
03511 offset = addr & 0xFFFF;
03512 break;
03513
03514 case 2:
03515 if((addr < 0xB0000) || (addr > 0xB7FFF))
03516 return 0xff;
03517 offset = addr & 0x7FFF;
03518 break;
03519
03520 case 3:
03521 if(addr < 0xB8000)
03522 return 0xff;
03523 offset = addr & 0x7FFF;
03524 break;
03525
03526 default:
03527 offset = addr & 0x1FFFF;
03528 }
03529
03530 if(state.sequencer.chain_four)
03531 {
03532
03533
03534 return state.memory[(offset &~0x03) + (offset % 4) * 65536];
03535 }
03536
03537 plane0 = &state.memory[0 << 16];
03538 plane1 = &state.memory[1 << 16];
03539 plane2 = &state.memory[2 << 16];
03540 plane3 = &state.memory[3 << 16];
03541
03542
03543 switch(state.graphics_ctrl.read_mode)
03544 {
03545 case 0:
03546 state.graphics_ctrl.latch[0] = plane0[offset];
03547 state.graphics_ctrl.latch[1] = plane1[offset];
03548 state.graphics_ctrl.latch[2] = plane2[offset];
03549 state.graphics_ctrl.latch[3] = plane3[offset];
03550 retval = state.graphics_ctrl.latch[state.graphics_ctrl.read_map_select];
03551 break;
03552
03553 case 1:
03554 {
03555 u8 color_compare;
03556
03557 u8 color_dont_care;
03558 u8 latch0;
03559 u8 latch1;
03560 u8 latch2;
03561 u8 latch3;
03562
03563 color_compare = state.graphics_ctrl.color_compare & 0x0f;
03564 color_dont_care = state.graphics_ctrl.color_dont_care & 0x0f;
03565 latch0 = state.graphics_ctrl.latch[0] = plane0[offset];
03566 latch1 = state.graphics_ctrl.latch[1] = plane1[offset];
03567 latch2 = state.graphics_ctrl.latch[2] = plane2[offset];
03568 latch3 = state.graphics_ctrl.latch[3] = plane3[offset];
03569
03570 latch0 ^= ccdat[color_compare][0];
03571 latch1 ^= ccdat[color_compare][1];
03572 latch2 ^= ccdat[color_compare][2];
03573 latch3 ^= ccdat[color_compare][3];
03574
03575 latch0 &= ccdat[color_dont_care][0];
03576 latch1 &= ccdat[color_dont_care][1];
03577 latch2 &= ccdat[color_dont_care][2];
03578 latch3 &= ccdat[color_dont_care][3];
03579
03580 retval = ~(latch0 | latch1 | latch2 | latch3);
03581 }
03582 break;
03583 }
03584
03585 return retval;
03586 }
03587
03592 void CCirrus::vga_mem_write(u32 addr, u8 value)
03593 {
03594 u32 offset;
03595 u8 new_val[4];
03596 unsigned start_addr;
03597 u8* plane0;
03598 u8 *plane1;
03599 u8 *plane2;
03600 u8 *plane3;
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610 switch(state.graphics_ctrl.memory_mapping)
03611 {
03612
03613 case 1:
03614 if(addr > 0xAFFFF)
03615 return;
03616 offset = addr - 0xA0000;
03617 break;
03618
03619
03620 case 2:
03621 if((addr < 0xB0000) || (addr > 0xB7FFF))
03622 return;
03623 offset = addr - 0xB0000;
03624 break;
03625
03626
03627 case 3:
03628 if(addr < 0xB8000)
03629 return;
03630 offset = addr - 0xB8000;
03631 break;
03632
03633
03634 default:
03635 offset = addr - 0xA0000;
03636 }
03637
03638 start_addr = (state.CRTC.reg[0x0c] << 8) | state.CRTC.reg[0x0d];
03639
03640 if(state.graphics_ctrl.graphics_alpha)
03641 {
03642 if(state.graphics_ctrl.memory_mapping == 3)
03643 {
03644
03645 unsigned x_tileno;
03646 unsigned x_tileno2;
03647 unsigned y_tileno;
03648
03649
03650 state.memory[offset] = value;
03651 offset -= start_addr;
03652 if(offset >= 0x2000)
03653 {
03654 y_tileno = offset - 0x2000;
03655 y_tileno /= (320 / 4);
03656 y_tileno <<= 1;
03657 y_tileno++;
03658 x_tileno = (offset - 0x2000) % (320 / 4);
03659 x_tileno <<= 2;
03660 }
03661 else
03662 {
03663 y_tileno = offset / (320 / 4);
03664 y_tileno <<= 1;
03665 x_tileno = offset % (320 / 4);
03666 x_tileno <<= 2;
03667 }
03668
03669 x_tileno2 = x_tileno;
03670 if(state.graphics_ctrl.shift_reg == 0)
03671 {
03672 x_tileno *= 2;
03673 x_tileno2 += 7;
03674 }
03675 else
03676 {
03677 x_tileno2 += 3;
03678 }
03679
03680 if(state.x_dotclockdiv2)
03681 {
03682 x_tileno /= (X_TILESIZE / 2);
03683 x_tileno2 /= (X_TILESIZE / 2);
03684 }
03685 else
03686 {
03687 x_tileno /= X_TILESIZE;
03688 x_tileno2 /= X_TILESIZE;
03689 }
03690
03691 if(state.y_doublescan)
03692 {
03693 y_tileno /= (Y_TILESIZE / 2);
03694 }
03695 else
03696 {
03697 y_tileno /= Y_TILESIZE;
03698 }
03699
03700 state.vga_mem_updated = 1;
03701 SET_TILE_UPDATED(x_tileno, y_tileno, 1);
03702 if(x_tileno2 != x_tileno)
03703 {
03704 SET_TILE_UPDATED(x_tileno2, y_tileno, 1);
03705 }
03706
03707 return;
03708
03709
03710 }
03711
03712 if(state.graphics_ctrl.memory_mapping != 1)
03713 {
03714 FAILURE_1(NotImplemented, "mem_write: graphics: mapping = %u \n",
03715 (unsigned) state.graphics_ctrl.memory_mapping);
03716 }
03717
03718 if(state.sequencer.chain_four)
03719 {
03720 unsigned x_tileno;
03721
03722 unsigned y_tileno;
03723
03724
03725 state.memory[(offset &~0x03) + (offset % 4) * 65536] = value;
03726 if(state.line_offset > 0)
03727 {
03728 offset -= start_addr;
03729 x_tileno = (offset % state.line_offset) / (X_TILESIZE / 2);
03730 if(state.y_doublescan)
03731 {
03732 y_tileno = (offset / state.line_offset) / (Y_TILESIZE / 2);
03733 }
03734 else
03735 {
03736 y_tileno = (offset / state.line_offset) / Y_TILESIZE;
03737 }
03738
03739 state.vga_mem_updated = 1;
03740 SET_TILE_UPDATED(x_tileno, y_tileno, 1);
03741 }
03742
03743 return;
03744 }
03745 }
03746
03747
03748 plane0 = &state.memory[0 << 16];
03749 plane1 = &state.memory[1 << 16];
03750 plane2 = &state.memory[2 << 16];
03751 plane3 = &state.memory[3 << 16];
03752
03753 switch(state.graphics_ctrl.write_mode)
03754 {
03755 unsigned i;
03756
03757 case 0:
03758 {
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780 const u8 bitmask = state.graphics_ctrl.bitmask;
03781 const u8 set_reset = state.graphics_ctrl.set_reset;
03782 const u8 enable_set_reset = state.graphics_ctrl.enable_set_reset;
03783
03784
03785 if(state.graphics_ctrl.data_rotate)
03786 {
03787 value = (value >> state.graphics_ctrl.data_rotate) | (value << (8 - state.graphics_ctrl.data_rotate));
03788 }
03789
03790 new_val[0] = state.graphics_ctrl.latch[0] &~bitmask;
03791 new_val[1] = state.graphics_ctrl.latch[1] &~bitmask;
03792 new_val[2] = state.graphics_ctrl.latch[2] &~bitmask;
03793 new_val[3] = state.graphics_ctrl.latch[3] &~bitmask;
03794 switch(state.graphics_ctrl.raster_op)
03795 {
03796 case 0:
03797 new_val[0] |=
03798 (
03799 (enable_set_reset & 1) ? ((set_reset & 1) ? bitmask : 0) :
03800 (value & bitmask)
03801 );
03802 new_val[1] |=
03803 (
03804 (enable_set_reset & 2) ? ((set_reset & 2) ? bitmask : 0) :
03805 (value & bitmask)
03806 );
03807 new_val[2] |=
03808 (
03809 (enable_set_reset & 4) ? ((set_reset & 4) ? bitmask : 0) :
03810 (value & bitmask)
03811 );
03812 new_val[3] |=
03813 (
03814 (enable_set_reset & 8) ? ((set_reset & 8) ? bitmask : 0) :
03815 (value & bitmask)
03816 );
03817 break;
03818
03819 case 1:
03820 new_val[0] |=
03821 (
03822 (enable_set_reset & 1) ?
03823 ((set_reset & 1) ? (state.graphics_ctrl.latch[0] & bitmask) : 0) :
03824 (value & state.graphics_ctrl.latch[0]) & bitmask
03825 );
03826 new_val[1] |=
03827 (
03828 (enable_set_reset & 2) ?
03829 ((set_reset & 2) ? (state.graphics_ctrl.latch[1] & bitmask) : 0) :
03830 (value & state.graphics_ctrl.latch[1]) & bitmask
03831 );
03832 new_val[2] |=
03833 (
03834 (enable_set_reset & 4) ?
03835 ((set_reset & 4) ? (state.graphics_ctrl.latch[2] & bitmask) : 0) :
03836 (value & state.graphics_ctrl.latch[2]) & bitmask
03837 );
03838 new_val[3] |=
03839 (
03840 (enable_set_reset & 8) ?
03841 ((set_reset & 8) ? (state.graphics_ctrl.latch[3] & bitmask) : 0) :
03842 (value & state.graphics_ctrl.latch[3]) & bitmask
03843 );
03844 break;
03845
03846 case 2:
03847 new_val[0] |=
03848 (
03849 (enable_set_reset & 1) ?
03850 (
03851 (set_reset & 1) ? bitmask :
03852 (state.graphics_ctrl.latch[0] & bitmask)
03853 ) : ((value | state.graphics_ctrl.latch[0]) & bitmask)
03854 );
03855 new_val[1] |=
03856 (
03857 (enable_set_reset & 2) ?
03858 (
03859 (set_reset & 2) ? bitmask :
03860 (state.graphics_ctrl.latch[1] & bitmask)
03861 ) : ((value | state.graphics_ctrl.latch[1]) & bitmask)
03862 );
03863 new_val[2] |=
03864 (
03865 (enable_set_reset & 4) ?
03866 (
03867 (set_reset & 4) ? bitmask :
03868 (state.graphics_ctrl.latch[2] & bitmask)
03869 ) : ((value | state.graphics_ctrl.latch[2]) & bitmask)
03870 );
03871 new_val[3] |=
03872 (
03873 (enable_set_reset & 8) ?
03874 (
03875 (set_reset & 8) ? bitmask :
03876 (state.graphics_ctrl.latch[3] & bitmask)
03877 ) : ((value | state.graphics_ctrl.latch[3]) & bitmask)
03878 );
03879 break;
03880
03881 case 3:
03882 new_val[0] |=
03883 (
03884 (enable_set_reset & 1) ?
03885 (
03886 (set_reset & 1) ? (~state.graphics_ctrl.latch[0] & bitmask) :
03887 (state.graphics_ctrl.latch[0] & bitmask)
03888 ) : (value ^ state.graphics_ctrl.latch[0]) & bitmask
03889 );
03890 new_val[1] |=
03891 (
03892 (enable_set_reset & 2) ?
03893 (
03894 (set_reset & 2) ? (~state.graphics_ctrl.latch[1] & bitmask) :
03895 (state.graphics_ctrl.latch[1] & bitmask)
03896 ) : (value ^ state.graphics_ctrl.latch[1]) & bitmask
03897 );
03898 new_val[2] |=
03899 (
03900 (enable_set_reset & 4) ?
03901 (
03902 (set_reset & 4) ? (~state.graphics_ctrl.latch[2] & bitmask) :
03903 (state.graphics_ctrl.latch[2] & bitmask)
03904 ) : (value ^ state.graphics_ctrl.latch[2]) & bitmask
03905 );
03906 new_val[3] |=
03907 (
03908 (enable_set_reset & 8) ?
03909 (
03910 (set_reset & 8) ? (~state.graphics_ctrl.latch[3] & bitmask) :
03911 (state.graphics_ctrl.latch[3] & bitmask)
03912 ) : (value ^ state.graphics_ctrl.latch[3]) & bitmask
03913 );
03914 break;
03915
03916 default:
03917 FAILURE_1(NotImplemented, "vga_mem_write: write mode 0: op = %u",
03918 (unsigned) state.graphics_ctrl.raster_op);
03919 }
03920 }
03921 break;
03922
03923
03924 case 1:
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935 for(i = 0; i < 4; i++)
03936 {
03937 new_val[i] = state.graphics_ctrl.latch[i];
03938 }
03939 break;
03940
03941
03942 case 2:
03943 {
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960 const u8 bitmask = state.graphics_ctrl.bitmask;
03961
03962 new_val[0] = state.graphics_ctrl.latch[0] &~bitmask;
03963 new_val[1] = state.graphics_ctrl.latch[1] &~bitmask;
03964 new_val[2] = state.graphics_ctrl.latch[2] &~bitmask;
03965 new_val[3] = state.graphics_ctrl.latch[3] &~bitmask;
03966 switch(state.graphics_ctrl.raster_op)
03967 {
03968 case 0:
03969 new_val[0] |= (value & 1) ? bitmask : 0;
03970 new_val[1] |= (value & 2) ? bitmask : 0;
03971 new_val[2] |= (value & 4) ? bitmask : 0;
03972 new_val[3] |= (value & 8) ? bitmask : 0;
03973 break;
03974
03975 case 1:
03976 new_val[0] |= (value & 1) ? (state.graphics_ctrl.latch[0] & bitmask) : 0;
03977 new_val[1] |= (value & 2) ? (state.graphics_ctrl.latch[1] & bitmask) : 0;
03978 new_val[2] |= (value & 4) ? (state.graphics_ctrl.latch[2] & bitmask) : 0;
03979 new_val[3] |= (value & 8) ? (state.graphics_ctrl.latch[3] & bitmask) : 0;
03980 break;
03981
03982 case 2:
03983 new_val[0] |= (value & 1) ? bitmask : (state.graphics_ctrl.latch[0] & bitmask);
03984 new_val[1] |= (value & 2) ? bitmask : (state.graphics_ctrl.latch[1] & bitmask);
03985 new_val[2] |= (value & 4) ? bitmask : (state.graphics_ctrl.latch[2] & bitmask);
03986 new_val[3] |= (value & 8) ? bitmask : (state.graphics_ctrl.latch[3] & bitmask);
03987 break;
03988
03989 case 3:
03990 new_val[0] |= (value & 1) ? (~state.graphics_ctrl.latch[0] & bitmask) : (state.graphics_ctrl.latch[0] & bitmask);
03991 new_val[1] |= (value & 2) ? (~state.graphics_ctrl.latch[1] & bitmask) : (state.graphics_ctrl.latch[1] & bitmask);
03992 new_val[2] |= (value & 4) ? (~state.graphics_ctrl.latch[2] & bitmask) : (state.graphics_ctrl.latch[2] & bitmask);
03993 new_val[3] |= (value & 8) ? (~state.graphics_ctrl.latch[3] & bitmask) : (state.graphics_ctrl.latch[3] & bitmask);
03994 break;
03995 }
03996 }
03997 break;
03998
03999
04000 case 3:
04001 {
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021 const u8 bitmask = state.graphics_ctrl.bitmask & value;
04022 const u8 set_reset = state.graphics_ctrl.set_reset;
04023
04024
04025 if(state.graphics_ctrl.data_rotate)
04026 {
04027 value = (value >> state.graphics_ctrl.data_rotate) | (value << (8 - state.graphics_ctrl.data_rotate));
04028 }
04029
04030 new_val[0] = state.graphics_ctrl.latch[0] &~bitmask;
04031 new_val[1] = state.graphics_ctrl.latch[1] &~bitmask;
04032 new_val[2] = state.graphics_ctrl.latch[2] &~bitmask;
04033 new_val[3] = state.graphics_ctrl.latch[3] &~bitmask;
04034
04035 value &= bitmask;
04036
04037 switch(state.graphics_ctrl.raster_op)
04038 {
04039 case 0:
04040 new_val[0] |= (set_reset & 1) ? value : 0;
04041 new_val[1] |= (set_reset & 2) ? value : 0;
04042 new_val[2] |= (set_reset & 4) ? value : 0;
04043 new_val[3] |= (set_reset & 8) ? value : 0;
04044 break;
04045
04046 case 1:
04047 new_val[0] |= ((set_reset & 1) ? value : 0) & state.graphics_ctrl.latch[0];
04048 new_val[1] |= ((set_reset & 2) ? value : 0) & state.graphics_ctrl.latch[1];
04049 new_val[2] |= ((set_reset & 4) ? value : 0) & state.graphics_ctrl.latch[2];
04050 new_val[3] |= ((set_reset & 8) ? value : 0) & state.graphics_ctrl.latch[3];
04051 break;
04052
04053 case 2:
04054 new_val[0] |= ((set_reset & 1) ? value : 0) | state.graphics_ctrl.latch[0];
04055 new_val[1] |= ((set_reset & 2) ? value : 0) | state.graphics_ctrl.latch[1];
04056 new_val[2] |= ((set_reset & 4) ? value : 0) | state.graphics_ctrl.latch[2];
04057 new_val[3] |= ((set_reset & 8) ? value : 0) | state.graphics_ctrl.latch[3];
04058 break;
04059
04060 case 3:
04061 new_val[0] |= ((set_reset & 1) ? value : 0) ^ state.graphics_ctrl.latch[0];
04062 new_val[1] |= ((set_reset & 2) ? value : 0) ^ state.graphics_ctrl.latch[1];
04063 new_val[2] |= ((set_reset & 4) ? value : 0) ^ state.graphics_ctrl.latch[2];
04064 new_val[3] |= ((set_reset & 8) ? value : 0) ^ state.graphics_ctrl.latch[3];
04065 break;
04066 }
04067 }
04068 break;
04069
04070 default:
04071 FAILURE_1(NotImplemented, "vga_mem_write: write mode %u ?",
04072 (unsigned) state.graphics_ctrl.write_mode);
04073 }
04074
04075
04076 if(state.sequencer.map_mask & 0x0f)
04077 {
04078 state.vga_mem_updated = 1;
04079 if(state.sequencer.map_mask & 0x01)
04080 plane0[offset] = new_val[0];
04081 if(state.sequencer.map_mask & 0x02)
04082 plane1[offset] = new_val[1];
04083 if(state.sequencer.map_mask & 0x04)
04084 {
04085
04086 if((offset & 0xe000) == state.charmap_address)
04087 {
04088
04089
04090 bx_gui->lock();
04091 bx_gui->set_text_charbyte((u16) (offset & 0x1fff), new_val[2]);
04092 bx_gui->unlock();
04093 }
04094
04095 plane2[offset] = new_val[2];
04096 }
04097
04098 if(state.sequencer.map_mask & 0x08)
04099 plane3[offset] = new_val[3];
04100
04101 unsigned x_tileno;
04102
04103 unsigned y_tileno;
04104
04105 if(state.graphics_ctrl.shift_reg == 2)
04106 {
04107 offset -= start_addr;
04108 x_tileno = (offset % state.line_offset) * 4 / (X_TILESIZE / 2);
04109 if(state.y_doublescan)
04110 {
04111 y_tileno = (offset / state.line_offset) / (Y_TILESIZE / 2);
04112 }
04113 else
04114 {
04115 y_tileno = (offset / state.line_offset) / Y_TILESIZE;
04116 }
04117
04118 SET_TILE_UPDATED(x_tileno, y_tileno, 1);
04119 }
04120 else
04121 {
04122 if(state.line_compare < state.vertical_display_end)
04123 {
04124 if(state.line_offset > 0)
04125 {
04126 if(state.x_dotclockdiv2)
04127 {
04128 x_tileno = (offset % state.line_offset) / (X_TILESIZE / 16);
04129 }
04130 else
04131 {
04132 x_tileno = (offset % state.line_offset) / (X_TILESIZE / 8);
04133 }
04134
04135 if(state.y_doublescan)
04136 {
04137 y_tileno =
04138 (
04139 (offset / state.line_offset) *
04140 2 +
04141 state.line_compare +
04142 1
04143 ) /
04144 Y_TILESIZE;
04145 }
04146 else
04147 {
04148 y_tileno = ((offset / state.line_offset) + state.line_compare + 1) / Y_TILESIZE;
04149 }
04150
04151 SET_TILE_UPDATED(x_tileno, y_tileno, 1);
04152 }
04153 }
04154
04155 if(offset >= start_addr)
04156 {
04157 offset -= start_addr;
04158 if(state.line_offset > 0)
04159 {
04160 if(state.x_dotclockdiv2)
04161 {
04162 x_tileno = (offset % state.line_offset) / (X_TILESIZE / 16);
04163 }
04164 else
04165 {
04166 x_tileno = (offset % state.line_offset) / (X_TILESIZE / 8);
04167 }
04168
04169 if(state.y_doublescan)
04170 {
04171 y_tileno = (offset / state.line_offset) / (Y_TILESIZE / 2);
04172 }
04173 else
04174 {
04175 y_tileno = (offset / state.line_offset) / Y_TILESIZE;
04176 }
04177
04178 SET_TILE_UPDATED(x_tileno, y_tileno, 1);
04179 }
04180 }
04181 }
04182 }
04183 }