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