diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 7ff2216da..294442bf4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -37,10 +37,13 @@ jobs: build: - name: Regular preset: regular + target: install/strip - name: Debug preset: debug + target: install - name: Dev preset: experimental + target: install environment: - msystem: MINGW32 prefix: mingw-w64-i686 @@ -74,7 +77,7 @@ jobs: -D CMAKE_INSTALL_PREFIX=./build/artifacts -D VNC=OFF - name: Build - run: cmake --build build --target install + run: cmake --build build --target ${{ matrix.build.target }} - uses: actions/upload-artifact@v2 with: name: '86Box-${{ matrix.build.name }}-MSYS2-${{ matrix.environment.msystem }}-${{ github.sha }}' diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e6552571..68b9e760e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ include(CPack) include(CMakeDependentOption) add_compile_definitions(CMAKE) -add_compile_definitions("$<$:DEBUG>") +add_compile_definitions("$<$:DEBUG>") if(WIN32) # Disables *_s function warnings diff --git a/CMakePresets.json b/CMakePresets.json index 8fc5f21a1..843727936 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -19,7 +19,8 @@ "CMAKE_C_FLAGS_OPTIMIZED": "-march=native -mtune=native -O3 -ffp-contract=last -flto", "CMAKE_CXX_FLAGS_OPTIMIZED": "-march=native -mtune=native -O3 -ffp-contract=last -flto" }, - "hidden": true + "hidden": true, + "binaryDir": "build" }, { "name": "regular", @@ -70,4 +71,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/86box.c b/src/86box.c index 3264a2959..82c847eaa 100644 --- a/src/86box.c +++ b/src/86box.c @@ -109,6 +109,7 @@ int confirm_exit_cmdl = 1; /* (O) do not ask for confirmation on quit if set t uint64_t unique_id = 0; uint64_t source_hwnd = 0; #endif +char rom_path[1024] = { '\0'}; /* (O) full path to ROMs */ char log_path[1024] = { '\0'}; /* (O) full path of logfile */ char vm_name[1024] = { '\0'}; /* (O) display name of the VM */ @@ -379,12 +380,13 @@ pc_log(const char *fmt, ...) int pc_init(int argc, char *argv[]) { - char path[2048]; + char path[2048], path2[2048]; char *cfg = NULL, *p; char temp[128]; struct tm *info; time_t now; - int c; + int c, vmrp = 0; + int ng = 0, lvmp = 0; uint32_t *uid, *shwnd; /* Grab the executable's full path. */ @@ -401,7 +403,10 @@ pc_init(int argc, char *argv[]) * could have been set to something else. */ plat_getcwd(usr_path, sizeof(usr_path) - 1); + plat_getcwd(rom_path, sizeof(rom_path) - 1); + memset(path, 0x00, sizeof(path)); + memset(path2, 0x00, sizeof(path)); for (c=1; cops && dev->ops->is_track_pre) + return dev->ops->is_track_pre(dev, lba); + + return 0; +} + + int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len) { diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 2df0801c3..91e4992b4 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -155,12 +155,28 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) if (track == -1) return 0; else { - cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr); + cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr); return attr == AUDIO_TRACK; } } +static int +image_is_track_pre(cdrom_t *dev, uint32_t lba) +{ + cd_img_t *img = (cd_img_t *)dev->image; + int track; + + /* GetTrack requires LBA. */ + track = cdi_get_track(img, lba); + + if (track != -1) + return cdi_get_audio_track_pre(img, track); + + return 0; +} + + static int image_sector_size(struct cdrom *dev, uint32_t lba) { @@ -231,6 +247,7 @@ static const cdrom_ops_t cdrom_image_ops = { image_get_tracks, image_get_track_info, image_get_subchannel, + image_is_track_pre, image_sector_size, image_read_sector, image_track_type, diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index cf4cb0005..ae6e4bb39 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -272,6 +272,18 @@ cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_ } +int +cdi_get_audio_track_pre(cd_img_t *cdi, int track) +{ + track_t *trk = &cdi->tracks[track - 1]; + + if ((track < 1) || (track > cdi->tracks_num)) + return 0; + + return trk->pre; +} + + /* This replaces both Info and EndInfo, they are specified by a variable. */ int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) @@ -709,6 +721,25 @@ cdi_cue_get_frame(uint64_t *frames, char **line) } +static int +cdi_cue_get_flags(track_t *cur, char **line) +{ + char temp[128], temp2[128]; + int success; + + success = cdi_cue_get_buffer(temp, line, 0); + if (! success) return 0; + + memset(temp2, 0x00, sizeof(temp2)); + success = sscanf(temp, "%s", temp2) == 1; + if (! success) return 0; + + cur->pre = (strstr(temp2, "PRE") != NULL); + + return 1; +} + + static int cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) { @@ -850,6 +881,8 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) trk.form = 0; trk.mode2 = 0; + trk.pre = 0; + if (!strcmp(type, "AUDIO")) { trk.sector_size = RAW_SECTOR_SIZE; trk.attr = AUDIO_TRACK; @@ -964,7 +997,9 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) } } else if (!strcmp(command, "PREGAP")) success = cdi_cue_get_frame(&cur_pregap, &line); - else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") || + else if (!strcmp(command, "FLAGS")) + success = cdi_cue_get_flags(&trk, &line); + else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { /* Ignored commands. */ diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index a410e72ba..7a3d97271 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -37,6 +37,7 @@ #include <86box/timer.h> #include <86box/nvr.h> #include <86box/acpi.h> +#include <86box/ddma.h> #include <86box/pci.h> #include <86box/pic.h> #include <86box/port_92.h> @@ -79,6 +80,7 @@ typedef struct sff8038i_t *bm[2]; nvr_t *nvr; int nvr_enabled, slot; + ddma_t *ddma; smbus_piix4_t *smbus; usb_t *usb[2]; acpi_t *acpi; @@ -708,6 +710,19 @@ usb_update_io_mapping(pipc_t *dev, int func) } +static void +pipc_ddma_update(pipc_t *dev, int addr) +{ + uint32_t base; + + if (dev->local >= VIA_PIPC_8231) + return; + + base = (dev->pci_isa_regs[addr] & 0xf0) | (((uint32_t) dev->pci_isa_regs[addr | 0x01]) << 8); + ddma_update_io_mapping(dev->ddma, (addr & 0x0e) >> 1, (dev->pci_isa_regs[addr] & 0xf0), dev->pci_isa_regs[addr | 0x01], (dev->pci_isa_regs[addr] & 0x08) && (base != 0x0000)); +} + + static void pipc_write(int func, int addr, uint8_t val, void *priv) { @@ -854,19 +869,13 @@ pipc_write(int func, int addr, uint8_t val, void *priv) case 0x60: case 0x62: case 0x64: case 0x66: case 0x6a: case 0x6c: case 0x6e: - c = (addr & 0x0e) >> 1; - dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0); - dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0); - if (val & 0x08) - dma_e |= (1 << c); - else - dma_e &= ~(1 << c); + dev->pci_isa_regs[addr] = val & 0xf8; + pipc_ddma_update(dev, addr); break; case 0x61: case 0x63: case 0x65: case 0x67: case 0x6b: case 0x6d: case 0x6f: - c = (addr & 0x0e) >> 1; - dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8); - dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8); + dev->pci_isa_regs[addr] = val; + pipc_ddma_update(dev, addr & 0xfe); break; case 0x70: case 0x71: case 0x72: case 0x73: @@ -1353,6 +1362,9 @@ pipc_init(const device_t *info) pci_enable_mirq(2); } + if (dev->local < VIA_PIPC_8231) + dev->ddma = device_add(&ddma_device); + if (dev->acpi) { acpi_set_slot(dev->acpi, dev->slot); acpi_set_nvr(dev->acpi, dev->nvr); diff --git a/src/config.c b/src/config.c index 2bab0af05..995bb801a 100644 --- a/src/config.c +++ b/src/config.c @@ -2584,12 +2584,12 @@ save_storage_controllers(void) else config_set_int(cat, "cassette_enabled", cassette_enable); - if (cassette_fname == NULL) + if (strlen(cassette_fname) == 0) config_delete_var(cat, "cassette_file"); else config_set_string(cat, "cassette_file", cassette_fname); - if (cassette_mode == NULL) + if (strlen(cassette_mode) == 0) config_delete_var(cat, "cassette_mode"); else config_set_string(cat, "cassette_mode", cassette_mode); diff --git a/src/cpu/386.c b/src/cpu/386.c index 743989e47..86327e5de 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -195,10 +195,14 @@ exec386(int cycs) cpu_state.oldpc = cpu_state.pc; x86_int(2); nmi_enable = 0; +#ifdef OLD_NMI_BEHAVIOR if (nmi_auto_clear) { nmi_auto_clear = 0; nmi = 0; } +#else + nmi = 0; +#endif } else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) { vector = picinterrupt(); if (vector != -1) { diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index a15e7a291..d396d122a 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -797,10 +797,14 @@ exec386_dynarec(int cycs) cpu_state.oldpc = cpu_state.pc; x86_int(2); nmi_enable = 0; +#ifdef OLD_NMI_BEHAVIOR if (nmi_auto_clear) { nmi_auto_clear = 0; nmi = 0; } +#else + nmi = 0; +#endif } else if ((cpu_state.flags & I_FLAG) && pic.int_pending) { vector = picinterrupt(); if (vector != -1) { diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 329ebe25f..3fbcfb0ed 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -968,6 +968,9 @@ check_interrupts(void) if (nmi && nmi_enable && nmi_mask) { nmi_enable = 0; interrupt(2); +#ifndef OLD_NMI_BEHAVIOR + nmi = 0; +#endif return; } if ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint) { diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 71ff383cd..4066036b4 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -79,6 +79,7 @@ extern int confirm_exit_cmdl; /* (O) do not ask for confirmation on quit if set extern uint64_t unique_id; extern uint64_t source_hwnd; #endif +extern char rom_path[1024]; /* (O) full path to ROMs */ extern char log_path[1024]; /* (O) full path of logfile */ extern char vm_name[1024]; /* (O) display name of the VM */ diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 759932198..95b806d30 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -83,6 +83,7 @@ typedef struct { void (*get_tracks)(struct cdrom *dev, int *first, int *last); void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti); void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc); + int (*is_track_pre)(struct cdrom *dev, uint32_t lba); int (*sector_size)(struct cdrom *dev, uint32_t lba); int (*read_sector)(struct cdrom *dev, int type, uint8_t *b, uint32_t lba); int (*track_type)(struct cdrom *dev, uint32_t lba); @@ -136,6 +137,7 @@ extern cdrom_t cdrom[CDROM_NUM]; extern int cdrom_lba_to_msf_accurate(int lba); extern double cdrom_seek_time(cdrom_t *dev); extern void cdrom_stop(cdrom_t *dev); +extern int cdrom_is_pre(cdrom_t *dev, uint32_t lba); extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len); extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf); extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit); diff --git a/src/include/86box/cdrom_image_backend.h b/src/include/86box/cdrom_image_backend.h index 5d5901320..74be1df69 100644 --- a/src/include/86box/cdrom_image_backend.h +++ b/src/include/86box/cdrom_image_backend.h @@ -58,7 +58,7 @@ typedef struct { typedef struct { int number, track_number, attr, sector_size, - mode2, form; + mode2, form, pre, pad; uint64_t start, length, skip; track_file_t *file; @@ -75,6 +75,7 @@ extern void cdi_close(cd_img_t *cdi); extern int cdi_set_device(cd_img_t *cdi, const char *path); extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); extern int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out); +extern int cdi_get_audio_track_pre(cd_img_t *cdi, int track); extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr); extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr); extern int cdi_get_track(cd_img_t *cdi, uint32_t sector); diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 78a13b346..10756dee3 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -129,7 +129,7 @@ typedef struct svga_t int override; void *p; - uint8_t crtc[256], gdcreg[64], attrregs[32], seqregs[256], + uint8_t crtc[256], gdcreg[256], attrregs[32], seqregs[256], egapal[16], *vram, *changedvram; @@ -267,6 +267,10 @@ extern float stg_getclock(int clock, void *p); extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); extern uint8_t tkd8001_ramdac_in(uint16_t addr, void *p, svga_t *svga); +extern void tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga); +extern uint8_t tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga); +extern void tvp3026_recalctimings(void *p, svga_t *svga); +extern void tvp3026_hwcursor_draw(svga_t *svga, int displine); #ifdef EMU_DEVICE_H extern const device_t ati68860_ramdac_device; @@ -295,4 +299,5 @@ extern const device_t stg_ramdac_device; extern const device_t tkd8001_ramdac_device; extern const device_t tseng_ics5301_ramdac_device; extern const device_t tseng_ics5341_ramdac_device; +extern const device_t tvp3026_ramdac_device; #endif diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 0c839ff9b..60af6c1b6 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -329,7 +329,10 @@ extern const device_t s3_diamond_stealth_vram_isa_device; extern const device_t s3_ami_86c924_isa_device; extern const device_t s3_metheus_86c928_isa_device; extern const device_t s3_metheus_86c928_vlb_device; -extern const device_t s3_v7mirage_86c801_isa_device; +extern const device_t s3_spea_mirage_86c801_isa_device; +extern const device_t s3_spea_mirage_86c805_vlb_device; +extern const device_t s3_mirocrystal_10sd_805_vlb_device; +extern const device_t s3_phoenix_86c801_isa_device; extern const device_t s3_phoenix_86c805_vlb_device; extern const device_t s3_bahamas64_vlb_device; extern const device_t s3_bahamas64_pci_device; @@ -339,10 +342,10 @@ extern const device_t s3_phoenix_trio32_vlb_device; extern const device_t s3_phoenix_trio32_pci_device; extern const device_t s3_diamond_stealth_se_vlb_device; extern const device_t s3_diamond_stealth_se_pci_device; +extern const device_t s3_spea_mirage_p64_vlb_device; extern const device_t s3_phoenix_trio64_vlb_device; extern const device_t s3_phoenix_trio64_onboard_pci_device; extern const device_t s3_phoenix_trio64_pci_device; -extern const device_t s3_phoenix_trio64vplus_vlb_device; extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; extern const device_t s3_phoenix_vision864_pci_device; @@ -353,10 +356,11 @@ extern const device_t s3_diamond_stealth64_pci_device; extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; extern const device_t s3_diamond_stealth64_964_vlb_device; +extern const device_t s3_mirovideo_40sv_968_pci_device; +extern const device_t s3_mirovideo_40sv_968_vlb_device; +extern const device_t s3_spea_mercury_p64v_pci_device; extern const device_t s3_elsa_winner2000_pro_x_964_pci_device; -extern const device_t s3_elsa_winner2000_pro_x_964_vlb_device; extern const device_t s3_elsa_winner2000_pro_x_pci_device; -extern const device_t s3_elsa_winner2000_pro_x_vlb_device; extern const device_t s3_trio64v2_dx_pci_device; extern const device_t s3_trio64v2_dx_onboard_pci_device; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index be44fa734..24fc1be51 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -1643,8 +1643,6 @@ vid_init_200(amstrad_t *ams) memset(vid, 0x00, sizeof(amsvid_t)); vid->emulation = device_get_config_int("video_emulation"); - cga_palette = (device_get_config_int("display_type") << 1); - ams_inform(vid); /* Default to CGA */ vid->dipswitches = 0x10; @@ -1677,6 +1675,9 @@ vid_init_200(amstrad_t *ams) cga_init(cga); mda_init(mda); + cga_palette = (device_get_config_int("display_type") << 1); + ams_inform(vid); + /* Attribute 8 is white on black (on a real MDA it's black on black) */ mda_setcol(0x08, 0, 1, 15); mda_setcol(0x88, 0, 1, 15); diff --git a/src/mem/rom.c b/src/mem/rom.c index 2f81957bf..3d7f28934 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -62,10 +62,35 @@ FILE * rom_fopen(char *fn, char *mode) { char temp[1024]; + char *fn2; - plat_append_filename(temp, exe_path, fn); + if ((strstr(fn, "roms/") == fn) || (strstr(fn, "roms\\") == fn)) { + /* Relative path */ + fn2 = (char *) malloc(strlen(fn) + 1); + memcpy(fn2, fn, strlen(fn) + 1); - return(plat_fopen(temp, mode)); + if (rom_path[0] != '\0') { + memset(fn2, 0x00, strlen(fn) + 1); + memcpy(fn2, &(fn[5]), strlen(fn) - 4); + + plat_append_filename(temp, rom_path, fn2); + } else { + /* Make sure to make it a backslash, just in case there's malformed + code calling us that assumes Windows. */ + if (fn2[4] == '\\') + fn2[4] = '/'; + + plat_append_filename(temp, exe_path, fn2); + } + + free(fn2); + fn2 = NULL; + + return(plat_fopen(temp, mode)); + } else { + /* Absolute path */ + return(plat_fopen(fn, mode)); + } } diff --git a/src/pit.c b/src/pit.c index dd4613d76..582c748a7 100644 --- a/src/pit.c +++ b/src/pit.c @@ -110,20 +110,20 @@ ctr_decrease_count(ctr_t *ctr) { if (ctr->bcd) { ctr->units--; - if (ctr->units == 0xff) { - ctr->units = 9; + if (ctr->units == -1) { + ctr->units = -7; ctr->tens--; - if (ctr->tens == 0xff) { - ctr->tens = 9; + if (ctr->tens == -1) { + ctr->tens = -7; ctr->hundreds--; - if (ctr->hundreds == 0xff) { - ctr->hundreds = 9; + if (ctr->hundreds == -1) { + ctr->hundreds = -7; ctr->thousands--; - if (ctr->thousands == 0xff) { - ctr->thousands = 9; + if (ctr->thousands == -1) { + ctr->thousands = -7; ctr->myriads--; - if (ctr->myriads == 0xff) - ctr->myriads = 0; /* 0 - 1 should wrap around to 9999. */ + if (ctr->myriads == -1) + ctr->myriads = -7; /* 0 - 1 should wrap around to 9999. */ } } } diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index d22b5fbf5..c48af0ae5 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -692,7 +692,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) ncr_dev->t128.host_pos = MIN(512, dev->buffer_length); ncr_dev->t128.status |= 0x04; - timer_on_auto(&ncr_dev->timer, 0.2); + timer_on_auto(&ncr_dev->timer, 0.02); } else { if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); diff --git a/src/sound/sound.c b/src/sound/sound.c index fa5d180ac..663983738 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -212,7 +212,8 @@ sound_cd_clean_buffers(void) static void sound_cd_thread(void *param) { - int c, r, i, channel_select[2]; + uint32_t lba; + int c, r, i, pre, channel_select[2]; double audio_vol_l, audio_vol_r; double cd_buffer_temp[2] = {0.0, 0.0}; @@ -231,9 +232,11 @@ sound_cd_thread(void *param) if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || (cdrom[i].cd_status == CD_STATUS_EMPTY)) continue; + lba = cdrom[i].seek_pos; r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2); if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r) continue; + pre = cdrom_is_pre(&(cdrom[i]), lba); if (cdrom[i].get_volume) { audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0)); @@ -277,6 +280,9 @@ sound_cd_thread(void *param) cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */ cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */ + + if (pre) + cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */ } if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) { @@ -286,6 +292,9 @@ sound_cd_thread(void *param) cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */ cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */ + + if (pre) + cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */ } /* Apply sound card CD volume and filters */ diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index db3b6e591..e5abdcd32 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -198,7 +198,8 @@ sdl_destroy_texture(void) void sdl_close(void) { - SDL_LockMutex(sdl_mutex); + if (sdl_mutex != NULL) + SDL_LockMutex(sdl_mutex); /* Unregister our renderer! */ video_setblit(NULL); diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 8624cd6f0..4b5f029b9 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -24,7 +24,7 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c vid_rtg310x.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c - vid_sdac_ramdac.c vid_ogc.c vid_nga.c) + vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c) if(MGA) target_compile_definitions(vid PRIVATE USE_MGA) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 2b30146b5..c78f28a10 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -41,12 +41,15 @@ #define ROM_DIAMOND_STEALTH_VRAM "roms/video/s3/Diamond Stealth VRAM BIOS v2.31 U14.BIN" #define ROM_AMI_86C924 "roms/video/s3/S3924AMI.BIN" #define ROM_METHEUS_86C928 "roms/video/s3/928.vbi" -#define ROM_V7MIRAGE_86C801 "roms/video/s3/v7mirage.vbi" -#define ROM_PHOENIX_86C805 "roms/video/s3/805.vbi" +#define ROM_SPEA_MIRAGE_86C801_V305I "roms/video/s3/V7MIRAGE.VBI" +#define ROM_SPEA_MIRAGE_86C801_V401 "roms/video/s3/S3_805VL_ATT20C491_SPEAmirage_VL_4.01.BIN" +#define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" +#define ROM_PHOENIX_86C80X "roms/video/s3/805.vbi" #define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" #define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom" #define ROM_PHOENIX_TRIO32 "roms/video/s3/86c732p.bin" +#define ROM_SPEA_MIRAGE_P64 "roms/video/s3/S3_764VL_SPEAMirageP64VL_ver5_03.BIN" #define ROM_NUMBER9_9FX "roms/video/s3/s3_764.bin" #define ROM_PHOENIX_TRIO64 "roms/video/s3/86c764x1.bin" #define ROM_DIAMOND_STEALTH64_764 "roms/video/s3/stealt64.bin" @@ -56,6 +59,8 @@ #define ROM_ELSAWIN2KPROX_964 "roms/video/s3/elsaw20004m.BIN" #define ROM_ELSAWIN2KPROX "roms/video/s3/elsaw20008m.BIN" #define ROM_PHOENIX_VISION868 "roms/video/s3/1-DSV3868.BIN" +#define ROM_MIROVIDEO40SV_968 "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" +#define ROM_SPEA_MERCURY_P64V "roms/video/s3/S3_968PCI_TVP3026_SPEAMecuryP64V_ver1.01.BIN" enum { @@ -67,7 +72,9 @@ enum S3_PHOENIX_TRIO64_ONBOARD, S3_PHOENIX_VISION864, S3_DIAMOND_STEALTH64_764, - S3_V7MIRAGE_86C801, + S3_SPEA_MIRAGE_86C801, + S3_SPEA_MIRAGE_86C805, + S3_PHOENIX_86C801, S3_PHOENIX_86C805, S3_ORCHID_86C911, S3_METHEUS_86C928, @@ -80,7 +87,11 @@ enum S3_DIAMOND_STEALTH_VRAM, S3_ELSAWIN2KPROX_964, S3_ELSAWIN2KPROX, - S3_PHOENIX_VISION868 + S3_PHOENIX_VISION868, + S3_MIROVIDEO40SV_968, + S3_MIROCRYSTAL10SD_805, + S3_SPEA_MIRAGE_P64, + S3_SPEA_MERCURY_P64V }; @@ -218,10 +229,11 @@ typedef struct s3_t uint16_t multifunc_cntl; uint16_t multifunc[16]; uint8_t pix_trans[4]; + int ssv_state; int cx, cy; int px, py; - int sx, sy; + int sx, sy, sx_backup; int dx, dy; uint32_t src, dest, pattern; @@ -236,6 +248,9 @@ typedef struct s3_t int dat_count; int b2e8_pix, temp_cnt; uint8_t cur_x_bit12, cur_y_bit12; + int ssv_len1, ssv_len2; + uint8_t ssv_dir1, ssv_dir2; + uint8_t ssv_draw1, ssv_draw2; } accel; struct { @@ -351,6 +366,8 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p); static void s3_accel_out_w(uint16_t port, uint16_t val, void *p); static void s3_accel_out_l(uint16_t port, uint32_t val, void *p); static uint8_t s3_accel_in(uint16_t port, void *p); +static uint16_t s3_accel_in_w(uint16_t port, void *p); +static uint32_t s3_accel_in_l(uint16_t port, void *p); static uint8_t s3_pci_read(int func, int addr, void *p); static void s3_pci_write(int func, int addr, uint8_t val, void *p); @@ -393,6 +410,53 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ } + +#define READ_PIXTRANS_BYTE_IO(n) \ + if (s3->bpp == 0) \ + s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & s3->vram_mask]; \ + else if (s3->bpp == 1) \ + s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 1)]; \ + else \ + s3->accel.pix_trans[n] = svga->vram[(s3->accel.dest + s3->accel.cx + n) & (s3->vram_mask >> 2)]; + +#define READ_PIXTRANS_BYTE_MM \ + if (s3->bpp == 0) \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ + else if (s3->bpp == 1) \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ + else \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; + +#define READ_PIXTRANS_WORD \ + if (s3->bpp == 0) { \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \ + } else if (s3->bpp == 1) { \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \ + } else { \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \ + } + +#define READ_PIXTRANS_LONG \ + if (s3->bpp == 0) { \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]; \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & s3->vram_mask] << 8); \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & s3->vram_mask] << 16); \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & s3->vram_mask] << 24); \ + } else if (s3->bpp == 1) { \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 1)]; \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 1)] << 8); \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 1)] << 16); \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 1)] << 24); \ + } else { \ + temp = svga->vram[(s3->accel.dest + s3->accel.cx) & (s3->vram_mask >> 2)]; \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 1) & (s3->vram_mask >> 2)] << 8); \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 2) & (s3->vram_mask >> 2)] << 16); \ + temp |= (svga->vram[(s3->accel.dest + s3->accel.cx + 3) & (s3->vram_mask >> 2)] << 24); \ + } + static int s3_cpu_src(s3_t *s3) { @@ -426,18 +490,14 @@ s3_cpu_dest(s3_t *s3) static int s3_accel_count(s3_t *s3) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) return 8; - else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) + else if (!(s3->accel.cmd & 0x200) && (s3->accel.cmd & 0x100)) return 1; - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 0x600) == 0x200) && (s3->accel.cmd & 0x100) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 0x600) == 0x200) && (s3->accel.cmd & 0x100) && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) return 16; - else if (((s3->accel.cmd & 0x600) == 0x200) && (s3->accel.cmd & 0x100)) + else if (((s3->accel.cmd & 0x200) == 0x200) && (s3->accel.cmd & 0x100)) return 2; - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x100) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - return 32; - else if (s3->accel.cmd & 0x100) - return 4; else return -1; } @@ -446,13 +506,24 @@ s3_accel_count(s3_t *s3) static int s3_data_len(s3_t *s3) { - if (!(s3->accel.cmd & 0x600)) + if (!(s3->accel.cmd & 0x200)) return 1; - if ((s3->accel.cmd & 0x600) == 0x200) - return 2; + return 2; +} - return 4; + +static int +s3_enable_fifo(s3_t *s3) +{ + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || + (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || + (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || + (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) + return 1; /* FIFO always enabled on these chips. */ + + //return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); + return 0; /*Disable FIFO on pre-964 cards due to glitches going around*/ } static void @@ -461,8 +532,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) svga_t *svga = &s3->svga; if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { @@ -477,7 +547,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) } } else { if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); else if (s3->accel.cmd & 0x400) s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); else { @@ -491,8 +561,7 @@ static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { if (s3->accel.cmd & 0x1000) val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); @@ -501,7 +570,7 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); s3_accel_start(8, 1, val & 0xff, 0, s3); } else if (s3->accel.cmd & 0x400) { - if (s3->accel.cmd & 0x1000) + if (s3->accel.cmd & 0x1000) val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); s3_accel_start(32, 1, val, 0, s3); } else if ((s3->accel.cmd & 0x600) == 0x200) { @@ -658,6 +727,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9949: case 0x9ae9: s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); + s3->accel.ssv_state = 0; s3_accel_start(-1, 0, 0xffffffff, 0, s3); s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ break; @@ -674,6 +744,9 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9d49: case 0x9ee9: s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + s3->accel.ssv_state = 1; + s3_accel_start(-1, 0, 0xffffffff, 0, s3); + s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ break; case 0xa148: case 0xa2e8: @@ -967,7 +1040,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[0] = val; if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); @@ -977,7 +1050,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[1] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: @@ -1034,7 +1107,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3_cpu_dest(s3)) break; s3->accel.pix_trans[3] = val; - if ((s3->accel.multifunc[0xa]& 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.multifunc[0xa]& 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: @@ -1213,7 +1286,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) if (svga->crtc[0x53] & 0x08) { if ((addr & 0x1ffff) < 0x8000) { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); else s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); @@ -1260,10 +1333,11 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else + else { s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } } } } @@ -1293,8 +1367,9 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) if (addr & 0x8000) { s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); - } else - s3_accel_out_pixtrans_w(s3, val); + } else { + s3_accel_out_pixtrans_w(s3, val); + } } } @@ -1500,8 +1575,9 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3_accel_write_fifo(s3, addr + 1, val >> 8); s3_accel_write_fifo(s3, addr + 2, val >> 16); s3_accel_write_fifo(s3, addr + 3, val >> 24); - } else + } else { s3_accel_out_pixtrans_l(s3, val); + } } } @@ -1595,7 +1671,8 @@ static void s3_hwcursor_draw(svga_t *svga, int displine) { s3_t *s3 = (s3_t *)svga->p; - int x; + int x, shift = 1; + int width = 16; uint16_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; @@ -1606,14 +1683,31 @@ s3_hwcursor_draw(svga_t *svga, int displine) case 15: fg = video_15to32[s3->hwc_fg_col & 0xffff]; bg = video_15to32[s3->hwc_bg_col & 0xffff]; + if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } + } break; case 16: fg = video_16to32[s3->hwc_fg_col & 0xffff]; bg = video_16to32[s3->hwc_bg_col & 0xffff]; + if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } + } break; - case 24: case 32: + case 24: + fg = s3->hwc_fg_col; + bg = s3->hwc_bg_col; + break; + + case 32: fg = s3->hwc_fg_col; bg = s3->hwc_bg_col; break; @@ -1637,8 +1731,8 @@ s3_hwcursor_draw(svga_t *svga, int displine) for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1]; - dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; + dat[0] = (svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_display_mask]; + dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_display_mask]; if (svga->crtc[0x55] & 0x10) { /*X11*/ for (xx = 0; xx < 16; xx++) { @@ -1648,12 +1742,12 @@ s3_hwcursor_draw(svga_t *svga, int displine) } offset++; - dat[0] <<= 1; - dat[1] <<= 1; + dat[0] <<= shift; + dat[1] <<= shift; } } else { /*Windows*/ - for (xx = 0; xx < 16; xx++) { + for (xx = 0; xx < width; xx++) { if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; @@ -1662,8 +1756,8 @@ s3_hwcursor_draw(svga_t *svga, int displine) } offset++; - dat[0] <<= 1; - dat[1] <<= 1; + dat[0] <<= shift; + dat[1] <<= shift; } } svga->hwcursor_latch.addr += 4; @@ -1974,12 +2068,12 @@ s3_io_remove_alt(s3_t *s3) if (s3->chip >= S3_86C928) io_removehandler(0xb148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else - io_removehandler(0xb148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_removehandler(0xb148, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_removehandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); io_removehandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2008,12 +2102,12 @@ s3_io_remove(s3_t *s3) if (s3->chip >= S3_86C928) io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else - io_removehandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_removehandler(0xb2e8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); io_removehandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2065,11 +2159,11 @@ s3_io_set_alt(s3_t *s3) if (s3->chip >= S3_86C928) io_sethandler(0xb148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else - io_sethandler(0xb148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_sethandler(0xb148, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_sethandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { io_sethandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2123,11 +2217,11 @@ s3_io_set(s3_t *s3) if (s3->chip >= S3_86C928) io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else - io_sethandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_sethandler(0xb2e8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2206,11 +2300,14 @@ s3_out(uint16_t addr, uint8_t val, void *p) if (!(svga->crtc[0x45] & 0x20) || (s3->chip == S3_86C928)) rs3 = !!(svga->crtc[0x55] & 0x02); else - rs3 = 0; + rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && s3->card_type == S3_ELSAWIN2KPROX)) ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); - else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V))) { + rs3 = !!(svga->crtc[0x55] & 0x02); + tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if (s3->chip <= S3_86C924) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); @@ -2329,6 +2426,8 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.x <<= 1; else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) svga->hwcursor.x >>= 1; + else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) + svga->hwcursor.x /= 3; break; case 0x4a: @@ -2369,7 +2468,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x55: if (s3->chip == S3_86C928) { - if (val & 0x08 || ((val & 0x20) == 0x20)) { + if ((val & 0x08) || ((val & 0x20) == 0x20)) { svga->hwcursor_draw = NULL; svga->dac_hwcursor_draw = bt48x_hwcursor_draw; } else { @@ -2478,9 +2577,12 @@ s3_in(uint16_t addr, void *p) else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && s3->card_type == S3_ELSAWIN2KPROX)) return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); - else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V))) { + rs3 = !!(svga->crtc[0x55] & 0x02); + return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); @@ -2519,7 +2621,7 @@ s3_in(uint16_t addr, void *p) /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ case 0x6b: - if (s3->chip != S3_TRIO64V2) { + if (s3->chip != S3_TRIO64V2 && s3->card_type != S3_MIROVIDEO40SV_968) { if (svga->crtc[0x53] & 0x08) { return (s3->chip == S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); } else { @@ -2529,7 +2631,7 @@ s3_in(uint16_t addr, void *p) return svga->crtc[0x6b]; break; case 0x6c: - if (s3->chip != S3_TRIO64V2) { + if (s3->chip != S3_TRIO64V2 && s3->card_type != S3_MIROVIDEO40SV_968) { if (svga->crtc[0x53] & 0x08) return 0x00; else @@ -2572,9 +2674,12 @@ static void s3_recalctimings(svga_t *svga) ibm_rgb528_recalctimings(svga->ramdac, svga); else bt48x_recalctimings(svga->ramdac, svga); - } else if (s3->chip == S3_VISION968) - ibm_rgb528_recalctimings(svga->ramdac, svga); - else + } else if (s3->chip == S3_VISION968) { + if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V) + tvp3026_recalctimings(svga->ramdac, svga); + else + ibm_rgb528_recalctimings(svga->ramdac, svga); + } else svga->interlace = svga->crtc[0x42] & 0x20; if ((((svga->miscout >> 2) & 3) == 3) && s3->chip < S3_TRIO32) @@ -2589,6 +2694,7 @@ static void s3_recalctimings(svga_t *svga) } svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { if (!(svga->crtc[0x14] & 0x40)) /*There are still accel issues with dword mode enabled, so disable dword mode for now.*/ @@ -2605,6 +2711,18 @@ static void s3_recalctimings(svga_t *svga) (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) { if (s3->width == 1280 || s3->width == 1600) svga->hdisp *= 2; + } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp *= 2; + } + + if (s3->card_type == S3_MIROVIDEO40SV_968) { + if (svga->hdisp != 1408) + svga->hdisp = s3->width; + } + if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (svga->rowoffset == 256 && ((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04))) + svga->rowoffset >>= 1; } } break; @@ -2612,7 +2730,8 @@ static void s3_recalctimings(svga_t *svga) svga->render = svga_render_15bpp_highres; if (s3->chip <= S3_86C924) svga->rowoffset >>= 1; - if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { + if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && + (s3->card_type != S3_SPEA_MIRAGE_86C805)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; else if (s3->chip != S3_VISION968) @@ -2628,24 +2747,41 @@ static void s3_recalctimings(svga_t *svga) svga->render = svga_render_16bpp_highres; if (s3->chip <= S3_86C924) svga->rowoffset >>= 1; - if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { + if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && + (s3->card_type != S3_SPEA_MIRAGE_86C805)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; else if (s3->chip != S3_VISION968) svga->hdisp /= 2; + } else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805)) { + svga->hdisp /= 2; } if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { if (s3->width == 1280 || s3->width == 1600) svga->hdisp *= 2; } + if (s3->card_type == S3_MIROVIDEO40SV_968) { + if (svga->hdisp == (1408*2)) + svga->hdisp /= 2; + else + svga->hdisp = s3->width; + } + + if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805) + svga->hdisp = s3->width; break; case 24: svga->render = svga_render_24bpp_highres; - if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805 && s3->chip != S3_VISION968) - svga->hdisp /= 3; - else - svga->hdisp = (svga->hdisp * 2) / 3; + if (s3->chip != S3_VISION968) { + if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) + svga->hdisp /= 3; + else + svga->hdisp = (svga->hdisp * 2) / 3; + } else { + if (s3->card_type == S3_MIROVIDEO40SV_968) + svga->hdisp = s3->width; + } break; case 32: svga->render = svga_render_32bpp_highres; @@ -2653,11 +2789,13 @@ static void s3_recalctimings(svga_t *svga) (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) { if (s3->chip == S3_VISION868) svga->hdisp /= 2; - else + else svga->hdisp /= 4; } - if (s3->width == 1280 || s3->width == 1600) + if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V)) svga->hdisp *= 2; + if (s3->card_type == S3_MIROVIDEO40SV_968) + svga->hdisp = s3->width; break; } } else { @@ -2892,7 +3030,7 @@ s3_updatemapping(s3_t *s3) } else { mem_mapping_disable(&s3->linear_mapping); } - + /* Memory mapped I/O. */ if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { mem_mapping_disable(&svga->mapping); @@ -2930,22 +3068,6 @@ s3_trio64_getclock(int clock, void *p) return t; } - -static int -s3_enable_fifo(s3_t *s3) -{ - svga_t *svga = &s3->svga; - - if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || - (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || - (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || - (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) - return 1; /* FIFO always enabled on these chips. */ - - return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); -} - - static void s3_accel_out(uint16_t port, uint8_t val, void *p) { @@ -2985,6 +3107,11 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) svga->fullchange = changeframecount; svga_recalctimings(svga); } + if (s3->chip <= S3_86C924) { + s3->width = (val & 4) ? 1024 : 640; + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } s3_updatemapping(s3); break; } @@ -3094,6 +3221,7 @@ s3_accel_in(uint16_t port, void *p) } break; + case 0x8118: case 0x9948: case 0x9ae8: temp = 0; /* FIFO empty */ if (!s3->blitter_busy) @@ -3101,6 +3229,7 @@ s3_accel_in(uint16_t port, void *p) if (FIFO_FULL && (s3->chip >= S3_VISION964)) temp = 0xff; /*FIFO full*/ return temp; /*FIFO empty*/ + case 0x8119: case 0x9949: case 0x9ae9: if (!s3->blitter_busy) wake_fifo_thread(s3); @@ -3351,53 +3480,118 @@ s3_accel_in(uint16_t port, void *p) case 0xe148: case 0xe2e8: if (!s3_cpu_dest(s3)) - break; + break; temp = s3->accel.pix_trans[0]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) - s3_accel_start(1, 1, 0xffffffff, 0xff, s3); + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(8, 1, 0xffffffff, 0, s3); + break; + case 0x200: + s3_accel_start(16, 1, 0xffffffff, 0, s3); + break; + } + } + } else { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + break; + case 0x200: + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + break; + } + } + } return temp; + case 0xe149: case 0xe2e9: if (!s3_cpu_dest(s3)) break; temp = s3->accel.pix_trans[1]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(16, 1, 0xffffffff, 0, s3); - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); - else if ((s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100)) - s3_accel_start(1, 1, 0xffffffff, 0xff, s3); + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(8, 1, 0xffffffff, 0, s3); + break; + case 0x200: + s3_accel_start(16, 1, 0xffffffff, 0, s3); + break; + } + } + } else { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + break; + case 0x200: + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + break; + } + } + } return temp; + case 0xe14a: case 0xe2ea: if (!s3_cpu_dest(s3)) break; temp = s3->accel.pix_trans[2]; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(8, 1, 0xffffffff, 0, s3); + break; + case 0x200: + s3_accel_start(16, 1, 0xffffffff, 0, s3); + break; + } + } + } else { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + break; + case 0x200: + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + break; + } + } + } return temp; + case 0xe14b: case 0xe2eb: if (!s3_cpu_dest(s3)) break; temp = s3->accel.pix_trans[3]; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x400) && (s3->accel.cmd & 0x100) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(32, 1, 0xffffffff, 0, s3); - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(16, 1, 0xffffffff, 0, s3); - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else if ((s3->accel.cmd & 0x400) && (s3->accel.cmd & 0x100)) - s3_accel_start(4, 1, 0xffffffff, 0xffffffff, s3); - else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); - else if ((s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100)) - s3_accel_start(1, 1, 0xffffffff, 0xff, s3); + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(8, 1, 0xffffffff, 0, s3); + break; + case 0x200: + s3_accel_start(16, 1, 0xffffffff, 0, s3); + break; + } + } + } else { + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x200) { + case 0x000: + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + break; + case 0x200: + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + break; + } + } + } return temp; case 0xff20: case 0xff21: @@ -3412,6 +3606,72 @@ s3_accel_in(uint16_t port, void *p) return 0xff; } +static uint16_t +s3_accel_in_w(uint16_t port, void *p) +{ + s3_t *s3 = (s3_t *)p; + uint16_t temp = 0x0000; + + if (!s3->enable_8514) + return 0xffff; + + if (s3_cpu_dest(s3)) { + temp = s3->accel.pix_trans[port & 2]; + temp |= s3->accel.pix_trans[(port & 2) + 1] << 8; + + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.cmd & 0x200) == 0x000) + s3_accel_start(8, 1, 0xffffffff, 0, s3); + else + s3_accel_start(16, 1, 0xffffffff, 0, s3); + } else { + if ((s3->accel.cmd & 0x200) == 0x000) + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + else + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + } + } + + return temp; +} + +static uint32_t +s3_accel_in_l(uint16_t port, void *p) +{ + s3_t *s3 = (s3_t *)p; + uint32_t temp = 0x00000000; + + if (!s3->enable_8514) + return 0xffffffff; + + if (s3_cpu_dest(s3)) { + temp = s3->accel.pix_trans[0]; + temp |= s3->accel.pix_trans[1] << 8; + temp |= s3->accel.pix_trans[2] << 16; + temp |= s3->accel.pix_trans[3] << 24; + + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.cmd & 0x200) == 0x000) { + s3_accel_start(8, 1, 0xffffffff, 0, s3); + s3_accel_start(8, 1, 0xffffffff, 0, s3); + } else { + s3_accel_start(16, 1, 0xffffffff, 0, s3); + s3_accel_start(16, 1, 0xffffffff, 0, s3); + } + } else { + if ((s3->accel.cmd & 0x200) == 0x000) { + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + } + } + } + + return temp; +} + static void s3_accel_write(uint32_t addr, uint8_t val, void *p) @@ -3420,7 +3680,7 @@ s3_accel_write(uint32_t addr, uint8_t val, void *p) svga_t *svga = &s3->svga; if (!s3->enable_8514) - return; + return; if (s3_enable_fifo(s3)) { if (svga->crtc[0x53] & 0x08) @@ -3438,7 +3698,7 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *p) svga_t *svga = &s3->svga; if (!s3->enable_8514) - return; + return; if (s3_enable_fifo(s3)) { if (svga->crtc[0x53] & 0x08) @@ -3456,7 +3716,7 @@ s3_accel_write_l(uint32_t addr, uint32_t val, void *p) svga_t *svga = &s3->svga; if (!s3->enable_8514) - return; + return; if (s3_enable_fifo(s3)) { if (svga->crtc[0x53] & 0x08) @@ -3507,14 +3767,19 @@ s3_accel_read(uint32_t addr, void *p) if (addr & 0x8000) { temp = s3_accel_in(addr & 0xffff, p); } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[addr & 3]; + temp = s3->accel.pix_trans[addr & 3]; - if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, 0xffffffff, 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); - } + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.cmd & 0x200) == 0x000) + s3_accel_start(8, 1, 0xffffffff, 0, s3); + else + s3_accel_start(16, 1, 0xffffffff, 0, s3); + } else { + if ((s3->accel.cmd & 0x200) == 0x000) + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + else + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + } } } @@ -3546,20 +3811,17 @@ s3_accel_read_w(uint32_t addr, void *p) temp = s3->accel.pix_trans[addr & 2]; temp |= s3->accel.pix_trans[(addr & 2) + 1] << 8; - if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x600) == 0x000) + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.cmd & 0x200) == 0x000) s3_accel_start(8, 1, 0xffff, 0, s3); else s3_accel_start(16, 1, 0xffff, 0, s3); } else { - if ((s3->accel.cmd & 0x600) == 0x000) + if ((s3->accel.cmd & 0x200) == 0x000) s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); else s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); } - } } } @@ -3695,35 +3957,28 @@ s3_accel_read_l(uint32_t addr, void *p) temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16; temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24; } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans[0]; + temp = s3->accel.pix_trans[0]; temp |= s3->accel.pix_trans[1] << 8; - temp |= s3->accel.pix_trans[2] << 16; + temp |= s3->accel.pix_trans[2] << 16; temp |= s3->accel.pix_trans[3] << 24; - if (s3->accel.cmd & 0x100) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && - (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if (s3->accel.cmd & 0x400) { - s3_accel_start(32, 1, 0xffffffff, 0, s3); - } else if ((s3->accel.cmd & 0x600) == 0x200) { - s3_accel_start(16, 1, 0xffff, 0, s3); - s3_accel_start(16, 1, 0xffff, 0, s3); - } else { - s3_accel_start(8, 1, 0xffff, 0, s3); - s3_accel_start(8, 1, 0xffff, 0, s3); - } - } else { - if (s3->accel.cmd & 0x400) - s3_accel_start(4, 1, 0xffffffff, 0xffffffff, s3); - else if ((s3->accel.cmd & 0x600) == 0x200) { - s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); - s3_accel_start(2, 1, 0xffffffff, 0xffff, s3); - } else { - s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); - s3_accel_start(1, 1, 0xffffffff, 0xffff, s3); - } - } - } + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && ((s3->accel.cmd & 2) || ((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if ((s3->accel.cmd & 0x200) == 0x000) { + s3_accel_start(8, 1, 0xffffffff, 0, s3); + s3_accel_start(8, 1, 0xffffffff, 0, s3); + } else { + s3_accel_start(16, 1, 0xffffffff, 0, s3); + s3_accel_start(16, 1, 0xffffffff, 0, s3); + } + } else { + if ((s3->accel.cmd & 0x200) == 0x000) { + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); + } + } } } @@ -3772,10 +4027,10 @@ polygon_setup(s3_t *s3) } } - #define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[(addr) & s3->vram_mask]; \ else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; + else if (s3->bpp == 2) dat = svga->vram[(addr) & s3->vram_mask]; \ + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; #define MIX_READ { \ switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ @@ -4088,6 +4343,11 @@ polygon_setup(s3_t *s3) vram_w[(addr) & (s3->vram_mask >> 1)] = dat; \ svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ } \ + else if (s3->bpp == 2) \ + { \ + svga->vram[(addr) & s3->vram_mask] = dat; \ + svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + } \ else \ { \ vram_l[(addr) & (s3->vram_mask >> 2)] = dat; \ @@ -4495,20 +4755,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->bpp == 1) { srcbase >>= 1; dstbase >>= 1; - } else if (s3->bpp == 3) { - srcbase >>= 2; - dstbase >>= 2; + } else if (s3->bpp == 3) { + srcbase >>= 2; + dstbase >>= 2; } - if ((s3->accel.cmd & 0x100) && (s3_cpu_src(s3) || s3_cpu_dest(s3)) && !cpu_input) { + if ((s3->accel.cmd & 0x100) && ((s3_cpu_src(s3) || (s3_cpu_dest(s3))) && !cpu_input)) { s3->force_busy = 1; } if (!cpu_input) s3->accel.dat_count = 0; - if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80) { - if (s3->bpp == 3 && count == 2) { + if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { + if ((s3->bpp == 3) && count == 2) { if (s3->accel.dat_count) { cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; count = 4; @@ -4537,11 +4797,147 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; break; } - if (s3->bpp == 0) compare &= 0xff; + if (s3->bpp == 0) compare &= 0xff; if (s3->bpp == 1) compare &= 0xffff; switch (cmd) { + case 0: /*NOP (Short Stroke Vectors)*/ + if (s3->accel.ssv_state == 0) + break; + + if (!cpu_input) { + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + if (s3->accel.cmd & 0x1000) { + s3->accel.ssv_len1 = (s3->accel.short_stroke >> 8) & 0x0f; + s3->accel.ssv_dir1 = (s3->accel.short_stroke >> 8) & 0xe0; + s3->accel.ssv_draw1 = (s3->accel.short_stroke >> 8) & 0x10; + s3->accel.ssv_len2 = s3->accel.short_stroke & 0x0f; + s3->accel.ssv_dir2 = s3->accel.short_stroke & 0xe0; + s3->accel.ssv_draw2 = s3->accel.short_stroke & 0x10; + } else { + s3->accel.ssv_len2 = (s3->accel.short_stroke >> 8) & 0x0f; + s3->accel.ssv_dir2 = (s3->accel.short_stroke >> 8) & 0xe0; + s3->accel.ssv_draw2 = (s3->accel.short_stroke >> 8) & 0x10; + s3->accel.ssv_len1 = s3->accel.short_stroke & 0x0f; + s3->accel.ssv_dir1 = s3->accel.short_stroke & 0xe0; + s3->accel.ssv_draw1 = s3->accel.short_stroke & 0x10; + } + + if (s3_cpu_src(s3)) { + return; /*Wait for data from CPU*/ + } + } + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + if (s3->accel.cmd & 8) /*Radial*/ + { + while (count-- && s3->accel.ssv_len1 >= 0) + { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) + { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + if (s3->accel.ssv_draw1) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + if (!s3->accel.ssv_len1) + break; + + switch (s3->accel.ssv_dir1 & 0xe0) + { + case 0x00: s3->accel.cx++; break; + case 0x20: s3->accel.cx++; s3->accel.cy--; break; + case 0x40: s3->accel.cy--; break; + case 0x60: s3->accel.cx--; s3->accel.cy--; break; + case 0x80: s3->accel.cx--; break; + case 0xa0: s3->accel.cx--; s3->accel.cy++; break; + case 0xc0: s3->accel.cy++; break; + case 0xe0: s3->accel.cx++; s3->accel.cy++; break; + } + s3->accel.ssv_len1--; + } + + while (count-- && s3->accel.ssv_len2 >= 0) + { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) + { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + if (s3->accel.ssv_draw2) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + if (!s3->accel.ssv_len2) + break; + + switch (s3->accel.ssv_dir2 & 0xe0) + { + case 0x00: s3->accel.cx++; break; + case 0x20: s3->accel.cx++; s3->accel.cy--; break; + case 0x40: s3->accel.cy--; break; + case 0x60: s3->accel.cx--; s3->accel.cy--; break; + case 0x80: s3->accel.cx--; break; + case 0xa0: s3->accel.cx--; s3->accel.cy++; break; + case 0xc0: s3->accel.cy++; break; + case 0xe0: s3->accel.cx++; s3->accel.cy++; break; + } + s3->accel.ssv_len2--; + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + case 1: /*Draw line*/ if (!cpu_input) { s3->accel.cx = s3->accel.cur_x; @@ -4555,6 +4951,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ return; /*Wait for data from CPU*/ } } + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -4578,10 +4975,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ compare_mode < 2) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - + MIX - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } } } @@ -4604,6 +5003,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0xc0: s3->accel.cy++; break; case 0xe0: s3->accel.cx++; s3->accel.cy++; break; } + s3->accel.sy--; } s3->accel.cur_x = s3->accel.cx; @@ -4642,7 +5042,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } } } @@ -4662,7 +5064,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!s3->accel.sy) { break; } - + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { s3->accel.err_term += s3->accel.destx_distp; /*Step minor axis*/ @@ -4693,6 +5095,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0xc0: s3->accel.cy++; break; case 0xe0: s3->accel.cy++; break; } + s3->accel.sy--; } s3->accel.cur_x = s3->accel.cx; @@ -4702,15 +5105,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 2: /*Rectangle fill*/ byte_cnt = s3_data_len(s3); - s3->data_available = 0; - + s3->data_available = 0; + if (!cpu_input) /*!cpu_input is trigger to start operation*/ { s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; s3->accel.cx = s3->accel.cur_x; s3->accel.cy = s3->accel.cur_y; - + if (s3->accel.cur_x_bit12) { if (s3->accel.cx <= 0x7ff) { s3->accel.cx = s3->accel.cur_x_bitres & 0xfff; @@ -4724,7 +5127,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } else { s3->accel.cy |= ~0xfff; } - } + } s3->accel.dest = dstbase + s3->accel.cy * s3->width; @@ -4737,7 +5140,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - + s3->accel.pix_trans[0] = 0xff; s3->accel.pix_trans[1] = 0xff; s3->accel.pix_trans[2] = 0xff; @@ -4753,11 +5156,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.b2e8_pix && s3_cpu_src(s3) && s3->accel.temp_cnt == 0) { mix_dat >>= 16; s3->accel.temp_cnt = 16; - } + } - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { + if (((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) || ((s3_cpu_dest(s3) && + (s3->accel.cy & 0xfff) >= clip_b))) /*For some reason, the SPEA v7 drivers want to draw the pixels beyond the clipping in read mode*/ + { if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (s3_cpu_dest(s3) && vram_mask) { @@ -4783,27 +5187,32 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - if (s3_cpu_dest(s3)) + if (s3_cpu_dest(s3)) { dest_dat = 0xffffffff; - else { + } else { READ(s3->accel.dest + s3->accel.cx, dest_dat); } MIX - + if (s3_cpu_dest(s3)) { - for (i = 0; i <= s3->bpp; i++) - s3->accel.pix_trans[read + i] = (src_dat >> (i << 3)) & 0xff; - /* Yes, src_dat is correct, there is no mixing/ROP's done on PIX_TRANS reads. */ - } else - WRITE(s3->accel.dest + s3->accel.cx, dest_dat); + if (s3->accel.cmd & 0x10) { + for (i = 0; i <= s3->bpp; i++) { + s3->accel.pix_trans[read + i] = (src_dat >> (i << 3)) & 0xff; + /* Yes, src_dat is correct, there is no mixing/ROP's done on PIX_TRANS reads. */ + } + } + } else { + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.cx, dest_dat); + } + } } } if (s3_cpu_dest(s3)) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && - (((s3->accel.frgd_mix & 0x60) != 0x40) || - ((s3->accel.bkgd_mix & 0x60) != 0x40))) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) && ((s3->accel.cmd & 2) || + ((s3->accel.frgd_mix & 0x60) != 0x40 || (s3->accel.bkgd_mix != 0x40)))) { read++; if (read >= (byte_cnt << 3)) s3->data_available = 1; /* Read data available. */ @@ -4825,20 +5234,33 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat |= 1; } - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; - if (s3->accel.cmd & 0x20) s3->accel.cx++; - else s3->accel.cx--; + if (s3->accel.cmd & 0x20) + s3->accel.cx++; + else + s3->accel.cx--; + s3->accel.sx--; if (s3->accel.sx < 0) { - if (s3->accel.cmd & 0x20) s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + if (s3->accel.cmd & 0x20) + { + s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + else + { + s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - if (s3->accel.cmd & 0x80) s3->accel.cy++; - else s3->accel.cy--; + if (s3->accel.cmd & 0x80) + s3->accel.cy++; + else + s3->accel.cy--; s3->accel.dest = dstbase + s3->accel.cy * s3->width; s3->accel.sy--; @@ -4856,7 +5278,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ return; } } - + if (s3_cpu_dest(s3) && s3->data_available) return; } @@ -4907,7 +5329,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + } } } if (s3->bpp == 0) cpu_dat >>= 8; @@ -5005,7 +5429,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask); - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } } s3->accel.cx++; @@ -5063,7 +5489,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } } } @@ -5185,7 +5613,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } } } @@ -5283,7 +5713,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } } } @@ -5317,7 +5749,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } } } @@ -5398,7 +5832,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); } + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + } + } } if (s3->bpp == 0) cpu_dat >>= 8; else cpu_dat >>= 16; @@ -5503,7 +5940,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ ROPMIX - WRITE(s3->accel.dest + s3->accel.dx, out); + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, out); + } } } @@ -5737,7 +6176,7 @@ static void *s3_init(const device_t *info) int chip, stepping; s3_t *s3 = malloc(sizeof(s3_t)); svga_t *svga = &s3->svga; - int vram; + int vram, spea_bios_ver; uint32_t vram_size; switch(info->local) { @@ -5756,13 +6195,27 @@ static void *s3_init(const device_t *info) chip = S3_86C924; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); break; - case S3_V7MIRAGE_86C801: - bios_fn = ROM_V7MIRAGE_86C801; + case S3_SPEA_MIRAGE_86C801: + spea_bios_ver = device_get_config_int("bios_ver"); + if (spea_bios_ver) + bios_fn = ROM_SPEA_MIRAGE_86C801_V401; + else + bios_fn = ROM_SPEA_MIRAGE_86C801_V305I; + chip = S3_86C801; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); + break; + case S3_MIROCRYSTAL10SD_805: + bios_fn = ROM_MIROCRYSTAL10SD_805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; + case S3_PHOENIX_86C801: + bios_fn = ROM_PHOENIX_86C80X; chip = S3_86C801; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); break; case S3_PHOENIX_86C805: - bios_fn = ROM_PHOENIX_86C805; + bios_fn = ROM_PHOENIX_86C80X; chip = S3_86C805; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); break; @@ -5806,22 +6259,29 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); break; - case S3_ELSAWIN2KPROX_964: - bios_fn = ROM_ELSAWIN2KPROX_964; - chip = S3_VISION964; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); - break; - case S3_ELSAWIN2KPROX: - bios_fn = ROM_ELSAWIN2KPROX; + case S3_MIROVIDEO40SV_968: + bios_fn = ROM_MIROVIDEO40SV_968; chip = S3_VISION968; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); break; + case S3_ELSAWIN2KPROX_964: + bios_fn = ROM_ELSAWIN2KPROX_964; + chip = S3_VISION964; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); + break; + case S3_ELSAWIN2KPROX: + bios_fn = ROM_ELSAWIN2KPROX; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; + case S3_SPEA_MERCURY_P64V: + bios_fn = ROM_SPEA_MERCURY_P64V; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; case S3_PHOENIX_TRIO32: bios_fn = ROM_PHOENIX_TRIO32; chip = S3_TRIO32; @@ -5846,6 +6306,11 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); break; + case S3_SPEA_MIRAGE_P64: + bios_fn = ROM_SPEA_MIRAGE_P64; + chip = S3_TRIO64; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; case S3_PHOENIX_TRIO64_ONBOARD: bios_fn = NULL; chip = S3_TRIO64; @@ -5903,7 +6368,10 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); - vram = device_get_config_int("memory"); + if (info->local == S3_MIROCRYSTAL10SD_805) + vram = 1; + else + vram = device_get_config_int("memory"); if (vram) vram_size = vram << 20; @@ -5969,8 +6437,10 @@ static void *s3_init(const device_t *info) if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; - else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || chip == S3_VISION968) + else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || (chip == S3_VISION968 && info->local == S3_ELSAWIN2KPROX)) svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; + else if (chip == S3_VISION968 && (info->local == S3_MIROVIDEO40SV_968 || info->local == S3_SPEA_MERCURY_P64V)) + svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; if (chip >= S3_VISION964) { switch (vram) { @@ -6008,7 +6478,7 @@ static void *s3_init(const device_t *info) else if (s3->vlb) svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); else - svga->crtc[0x36] = 3; + svga->crtc[0x36] = 3 | (1 << 4); if (chip >= S3_86C928) svga->crtc[0x36] |= (vram_sizes[vram] << 5); @@ -6016,6 +6486,9 @@ static void *s3_init(const device_t *info) svga->crtc[0x36] |= ((vram == 1) ? 0x00 : 0x20) | 0x80; svga->crtc[0x37] = 1 | (7 << 5); + + if (chip >= S3_86C928) + svga->crtc[0x37] |= 0x04; svga->vblank_start = s3_vblank_start; @@ -6042,7 +6515,6 @@ static void *s3_init(const device_t *info) s3->id_ext = stepping; s3->id_ext_pci = 0; s3->packed_mmio = 0; - s3->width = 1024; svga->ramdac = device_add(&sc11483_ramdac_device); svga->clock_gen = device_add(&av9194_device); @@ -6063,7 +6535,7 @@ static void *s3_init(const device_t *info) svga->getclock = ics2494_getclock; break; - case S3_V7MIRAGE_86C801: + case S3_MIROCRYSTAL10SD_805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ s3->id = stepping; @@ -6072,11 +6544,27 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 0; svga->crtc[0x5a] = 0x0a; - svga->ramdac = device_add(&att491_ramdac_device); + svga->ramdac = device_add(&gendac_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = sdac_getclock; + break; + + case S3_SPEA_MIRAGE_86C801: + case S3_SPEA_MIRAGE_86C805: + svga->decode_mask = (2 << 20) - 1; + stepping = 0xa0; /*86C801/86C805*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; + + svga->ramdac = device_add(&att490_ramdac_device); svga->clock_gen = device_add(&av9194_device); svga->getclock = av9194_getclock; break; + case S3_PHOENIX_86C801: case S3_PHOENIX_86C805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ @@ -6133,9 +6621,12 @@ static void *s3_init(const device_t *info) svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb528_ramdac_device) : device_add(&bt485_ramdac_device); svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - break; + break; + case S3_ELSAWIN2KPROX: + case S3_MIROVIDEO40SV_968: + case S3_SPEA_MERCURY_P64V: svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision968*/ s3->id_ext = s3->id_ext_pci = 0xf0; @@ -6151,8 +6642,12 @@ static void *s3_init(const device_t *info) svga->crtc[0x59] = 0x00; svga->crtc[0x5a] = 0x0a; } + + if (info->local == S3_ELSAWIN2KPROX) + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); + else + svga->ramdac = device_add(&tvp3026_ramdac_device); - svga->ramdac = device_add(&ibm_rgb528_ramdac_device); svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; break; @@ -6197,6 +6692,7 @@ static void *s3_init(const device_t *info) case S3_PHOENIX_TRIO64VPLUS: case S3_PHOENIX_TRIO64VPLUS_ONBOARD: case S3_DIAMOND_STEALTH64_764: + case S3_SPEA_MIRAGE_P64: if (device_get_config_int("memory") == 1) svga->vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ /* Fall over. */ @@ -6208,8 +6704,7 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 1; if (info->local == S3_PHOENIX_TRIO64VPLUS || info->local == S3_PHOENIX_TRIO64VPLUS_ONBOARD) { - if (s3->pci) - svga->crtc[0x53] = 0x08; + svga->crtc[0x53] = 0x08; } svga->clock_gen = s3; @@ -6248,7 +6743,7 @@ static void *s3_init(const device_t *info) s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c)); svga->packed_chain4 = 1; - + s3->wake_fifo_thread = thread_create_event(); s3->fifo_not_full_event = thread_create_event(); s3->thread_run = 1; @@ -6272,14 +6767,19 @@ static int s3_ami_86c924_available(void) return rom_present(ROM_AMI_86C924); } -static int s3_v7mirage_86c801_available(void) +static int s3_spea_mirage_86c801_available(void) { - return rom_present(ROM_V7MIRAGE_86C801); + return rom_present(ROM_SPEA_MIRAGE_86C801_V305I) && rom_present(ROM_SPEA_MIRAGE_86C801_V401); } -static int s3_phoenix_86c805_available(void) +static int s3_phoenix_86c80x_available(void) { - return rom_present(ROM_PHOENIX_86C805); + return rom_present(ROM_PHOENIX_86C80X); +} + +static int s3_mirocrystal_10sd_805_available(void) +{ + return rom_present(ROM_MIROCRYSTAL10SD_805); } static int s3_metheus_86c928_available(void) @@ -6307,6 +6807,16 @@ static int s3_diamond_stealth64_964_available(void) return rom_present(ROM_DIAMOND_STEALTH64_964); } +static int s3_mirovideo_40sv_968_available(void) +{ + return rom_present(ROM_MIROVIDEO40SV_968); +} + +static int s3_spea_mercury_p64v_pci_available(void) +{ + return rom_present(ROM_SPEA_MERCURY_P64V); +} + static int s3_elsa_winner2000_pro_x_964_available(void) { return rom_present(ROM_ELSAWIN2KPROX_964); @@ -6332,6 +6842,11 @@ static int s3_9fx_available(void) return rom_present(ROM_NUMBER9_9FX); } +static int s3_spea_mirage_p64_vlb_available(void) +{ + return rom_present(ROM_SPEA_MIRAGE_P64); +} + static int s3_phoenix_trio64_available(void) { return rom_present(ROM_PHOENIX_TRIO64); @@ -6357,7 +6872,7 @@ static void s3_close(void *p) s3_t *s3 = (s3_t *)p; svga_close(&s3->svga); - + s3->thread_run = 0; thread_set_event(s3->wake_fifo_thread); thread_wait(s3->fifo_thread, -1); @@ -6427,6 +6942,42 @@ static const device_config_t s3_9fx_config[] = } }; + +static const device_config_t s3_spea_mirage_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 2, "", { 0 }, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "" + } + } + }, + { + "bios_ver", "BIOS version", CONFIG_SELECTION, "", 1, "", { 0 }, + { + { + "3.05I", 0 + }, + { + "4.01", 1 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + static const device_config_t s3_phoenix_trio32_config[] = { { @@ -6504,7 +7055,7 @@ static const device_config_t s3_968_config[] = const device_t s3_orchid_86c911_isa_device = { - "Orchid Fahrenheit 1280 (S3 86c911) ISA", + "S3 86c911 ISA (Orchid Fahrenheit 1280)", DEVICE_AT | DEVICE_ISA, S3_ORCHID_86C911, s3_init, @@ -6518,7 +7069,7 @@ const device_t s3_orchid_86c911_isa_device = const device_t s3_diamond_stealth_vram_isa_device = { - "Diamond Stealth VRAM (S3 86c911) ISA", + "S3 86c911 ISA (Diamond Stealth VRAM)", DEVICE_AT | DEVICE_ISA, S3_DIAMOND_STEALTH_VRAM, s3_init, @@ -6532,7 +7083,7 @@ const device_t s3_diamond_stealth_vram_isa_device = const device_t s3_ami_86c924_isa_device = { - "AMI S3 86c924 ISA", + "S3 86c924 ISA (AMI)", DEVICE_AT | DEVICE_ISA, S3_AMI_86C924, s3_init, @@ -6544,15 +7095,43 @@ const device_t s3_ami_86c924_isa_device = s3_orchid_86c911_config }; -const device_t s3_v7mirage_86c801_isa_device = +const device_t s3_spea_mirage_86c801_isa_device = { - "SPEA V7 Mirage (S3 86c801) ISA", + "S3 86c801 ISA (SPEA Mirage ISA)", DEVICE_AT | DEVICE_ISA, - S3_V7MIRAGE_86C801, + S3_SPEA_MIRAGE_86C801, s3_init, s3_close, NULL, - { s3_v7mirage_86c801_available }, + { s3_spea_mirage_86c801_available }, + s3_speed_changed, + s3_force_redraw, + s3_spea_mirage_config +}; + +const device_t s3_mirocrystal_10sd_805_vlb_device = +{ + "S3 86c805 VLB (MiroCrystal 10SD)", + DEVICE_VLB, + S3_MIROCRYSTAL10SD_805, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_10sd_805_available }, + s3_speed_changed, + s3_force_redraw, + NULL +}; + +const device_t s3_phoenix_86c801_isa_device = +{ + "S3 86c801 ISA (Phoenix)", + DEVICE_AT | DEVICE_ISA, + S3_PHOENIX_86C801, + s3_init, + s3_close, + NULL, + { s3_phoenix_86c80x_available }, s3_speed_changed, s3_force_redraw, s3_9fx_config @@ -6560,13 +7139,13 @@ const device_t s3_v7mirage_86c801_isa_device = const device_t s3_phoenix_86c805_vlb_device = { - "Phoenix S3 86c805 VLB", + "S3 86c805 VLB (Phoenix)", DEVICE_VLB, S3_PHOENIX_86C805, s3_init, s3_close, NULL, - { s3_phoenix_86c805_available }, + { s3_phoenix_86c80x_available }, s3_speed_changed, s3_force_redraw, s3_9fx_config @@ -6574,7 +7153,7 @@ const device_t s3_phoenix_86c805_vlb_device = const device_t s3_metheus_86c928_isa_device = { - "Metheus Premier 928 (S3 86c928) ISA", + "S3 86c928 ISA (Metheus Premier 928)", DEVICE_AT | DEVICE_ISA, S3_METHEUS_86C928, s3_init, @@ -6588,7 +7167,7 @@ const device_t s3_metheus_86c928_isa_device = const device_t s3_metheus_86c928_vlb_device = { - "Metheus Premier 928 (S3 86c928) VLB", + "S3 86c928 VLB (Metheus Premier 928)", DEVICE_VLB, S3_METHEUS_86C928, s3_init, @@ -6600,23 +7179,9 @@ const device_t s3_metheus_86c928_vlb_device = s3_standard_config }; -const device_t s3_metheus_86c928_pci_device = -{ - "Metheus Premier 928 (S3 86c928) PCI", - DEVICE_PCI, - S3_METHEUS_86C928, - s3_init, - s3_close, - NULL, - { s3_metheus_86c928_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config -}; - const device_t s3_bahamas64_vlb_device = { - "Paradise Bahamas 64 (S3 Vision864) VLB", + "S3 Vision864 VLB (Paradise Bahamas 64)", DEVICE_VLB, S3_PARADISE_BAHAMAS64, s3_init, @@ -6630,7 +7195,7 @@ const device_t s3_bahamas64_vlb_device = const device_t s3_bahamas64_pci_device = { - "Paradise Bahamas 64 (S3 Vision864) PCI", + "S3 Vision864 PCI (Paradise Bahamas 64)", DEVICE_PCI, S3_PARADISE_BAHAMAS64, s3_init, @@ -6644,7 +7209,7 @@ const device_t s3_bahamas64_pci_device = const device_t s3_diamond_stealth64_964_vlb_device = { - "S3 Vision964 (Diamond Stealth64 VRAM) VLB", + "S3 Vision964 VLB (Diamond Stealth64 VRAM)", DEVICE_VLB, S3_DIAMOND_STEALTH64_964, s3_init, @@ -6658,7 +7223,7 @@ const device_t s3_diamond_stealth64_964_vlb_device = const device_t s3_diamond_stealth64_964_pci_device = { - "S3 Vision964 (Diamond Stealth64 VRAM) PCI", + "S3 Vision964 PCI (Diamond Stealth64 VRAM)", DEVICE_PCI, S3_DIAMOND_STEALTH64_964, s3_init, @@ -6670,9 +7235,51 @@ const device_t s3_diamond_stealth64_964_pci_device = s3_standard_config }; +const device_t s3_mirovideo_40sv_968_vlb_device = +{ + "S3 Vision968 VLB (MiroVIDEO 40SV)", + DEVICE_VLB, + S3_MIROVIDEO40SV_968, + s3_init, + s3_close, + NULL, + { s3_mirovideo_40sv_968_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + +const device_t s3_mirovideo_40sv_968_pci_device = +{ + "S3 Vision968 PCI (MiroVIDEO 40SV)", + DEVICE_PCI, + S3_MIROVIDEO40SV_968, + s3_init, + s3_close, + NULL, + { s3_mirovideo_40sv_968_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + +const device_t s3_spea_mercury_p64v_pci_device = +{ + "S3 Vision968 PCI (SPEA Mercury P64V)", + DEVICE_PCI, + S3_SPEA_MERCURY_P64V, + s3_init, + s3_close, + NULL, + { s3_spea_mercury_p64v_pci_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + const device_t s3_9fx_vlb_device = { - "Number 9 9FX (S3 Trio64) VLB", + "S3 Trio64 VLB (Number 9 9FX 330)", DEVICE_VLB, S3_NUMBER9_9FX, s3_init, @@ -6686,7 +7293,7 @@ const device_t s3_9fx_vlb_device = const device_t s3_9fx_pci_device = { - "Number 9 9FX (S3 Trio64) PCI", + "S3 Trio64 PCI (Number 9 9FX 330)", DEVICE_PCI, S3_NUMBER9_9FX, s3_init, @@ -6700,7 +7307,7 @@ const device_t s3_9fx_pci_device = const device_t s3_phoenix_trio32_vlb_device = { - "Phoenix S3 Trio32 VLB", + "S3 Trio32 VLB (Phoenix)", DEVICE_VLB, S3_PHOENIX_TRIO32, s3_init, @@ -6714,7 +7321,7 @@ const device_t s3_phoenix_trio32_vlb_device = const device_t s3_phoenix_trio32_pci_device = { - "Phoenix S3 Trio32 PCI", + "S3 Trio32 PCI (Phoenix)", DEVICE_PCI, S3_PHOENIX_TRIO32, s3_init, @@ -6728,7 +7335,7 @@ const device_t s3_phoenix_trio32_pci_device = const device_t s3_diamond_stealth_se_vlb_device = { - "Diamond Stealth SE (S3 Trio32) VLB", + "S3 Trio32 VLB (Diamond Stealth SE)", DEVICE_VLB, S3_DIAMOND_STEALTH_SE, s3_init, @@ -6742,7 +7349,7 @@ const device_t s3_diamond_stealth_se_vlb_device = const device_t s3_diamond_stealth_se_pci_device = { - "Diamond Stealth SE (S3 Trio32) PCI", + "S3 Trio32 PCI (Diamond Stealth SE)", DEVICE_PCI, S3_DIAMOND_STEALTH_SE, s3_init, @@ -6757,7 +7364,7 @@ const device_t s3_diamond_stealth_se_pci_device = const device_t s3_phoenix_trio64_vlb_device = { - "Phoenix S3 Trio64 VLB", + "S3 Trio64 VLB (Phoenix)", DEVICE_VLB, S3_PHOENIX_TRIO64, s3_init, @@ -6771,7 +7378,7 @@ const device_t s3_phoenix_trio64_vlb_device = const device_t s3_phoenix_trio64_onboard_pci_device = { - "Phoenix S3 Trio64 On-Board PCI", + "S3 Trio64 PCI On-Board (Phoenix)", DEVICE_PCI, S3_PHOENIX_TRIO64_ONBOARD, s3_init, @@ -6785,7 +7392,7 @@ const device_t s3_phoenix_trio64_onboard_pci_device = const device_t s3_phoenix_trio64_pci_device = { - "Phoenix S3 Trio64 PCI", + "S3 Trio64 PCI (Phoenix)", DEVICE_PCI, S3_PHOENIX_TRIO64, s3_init, @@ -6797,23 +7404,9 @@ const device_t s3_phoenix_trio64_pci_device = s3_standard_config }; -const device_t s3_phoenix_trio64vplus_vlb_device = -{ - "Phoenix S3 Trio64V+ VLB", - DEVICE_VLB, - S3_PHOENIX_TRIO64VPLUS, - s3_init, - s3_close, - NULL, - { s3_phoenix_trio64vplus_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config -}; - const device_t s3_phoenix_trio64vplus_onboard_pci_device = { - "Phoenix S3 Trio64V+ On-Board PCI", + "S3 Trio64V+ PCI On-Board (Phoenix)", DEVICE_PCI, S3_PHOENIX_TRIO64VPLUS_ONBOARD, s3_init, @@ -6827,7 +7420,7 @@ const device_t s3_phoenix_trio64vplus_onboard_pci_device = const device_t s3_phoenix_trio64vplus_pci_device = { - "Phoenix S3 Trio64V+ PCI", + "S3 Trio64V+ PCI (Phoenix)", DEVICE_PCI, S3_PHOENIX_TRIO64VPLUS, s3_init, @@ -6841,7 +7434,7 @@ const device_t s3_phoenix_trio64vplus_pci_device = const device_t s3_phoenix_vision864_vlb_device = { - "Phoenix S3 Vision864 VLB", + "S3 Vision864 VLB (Phoenix)", DEVICE_VLB, S3_PHOENIX_VISION864, s3_init, @@ -6855,7 +7448,7 @@ const device_t s3_phoenix_vision864_vlb_device = const device_t s3_phoenix_vision864_pci_device = { - "Phoenix S3 Vision864 PCI", + "S3 Vision864 PCI (Phoenix)", DEVICE_PCI, S3_PHOENIX_VISION864, s3_init, @@ -6869,7 +7462,7 @@ const device_t s3_phoenix_vision864_pci_device = const device_t s3_phoenix_vision868_vlb_device = { - "Phoenix S3 Vision868 VLB", + "S3 Vision868 VLB (Phoenix)", DEVICE_VLB, S3_PHOENIX_VISION868, s3_init, @@ -6883,7 +7476,7 @@ const device_t s3_phoenix_vision868_vlb_device = const device_t s3_phoenix_vision868_pci_device = { - "Phoenix S3 Vision868 PCI", + "S3 Vision868 PCI (Phoenix)", DEVICE_PCI, S3_PHOENIX_VISION868, s3_init, @@ -6897,7 +7490,7 @@ const device_t s3_phoenix_vision868_pci_device = const device_t s3_diamond_stealth64_vlb_device = { - "S3 Trio64 (Diamond Stealth64 DRAM) VLB", + "S3 Trio64 VLB (Diamond Stealth64 DRAM)", DEVICE_VLB, S3_DIAMOND_STEALTH64_764, s3_init, @@ -6911,7 +7504,7 @@ const device_t s3_diamond_stealth64_vlb_device = const device_t s3_diamond_stealth64_pci_device = { - "S3 Trio64 (Diamond Stealth64 DRAM) PCI", + "S3 Trio64 PCI (Diamond Stealth64 DRAM)", DEVICE_PCI, S3_DIAMOND_STEALTH64_764, s3_init, @@ -6923,24 +7516,24 @@ const device_t s3_diamond_stealth64_pci_device = s3_9fx_config }; -const device_t s3_elsa_winner2000_pro_x_964_pci_device = +const device_t s3_spea_mirage_p64_vlb_device = { - "S3 Vision964 (ELSA Winner 2000 Pro/X) PCI", - DEVICE_PCI, - S3_ELSAWIN2KPROX_964, - s3_init, - s3_close, + "S3 Trio64 VLB (SPEA Mirage P64)", + DEVICE_VLB, + S3_SPEA_MIRAGE_P64, + s3_init, + s3_close, NULL, - { s3_elsa_winner2000_pro_x_964_available }, - s3_speed_changed, - s3_force_redraw, - s3_968_config + { s3_spea_mirage_p64_vlb_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config }; -const device_t s3_elsa_winner2000_pro_x_964_vlb_device = +const device_t s3_elsa_winner2000_pro_x_964_pci_device = { - "S3 Vision964 (ELSA Winner 2000 Pro/X) VLB", - DEVICE_VLB, + "S3 Vision964 PCI (ELSA Winner 2000 Pro/X)", + DEVICE_PCI, S3_ELSAWIN2KPROX_964, s3_init, s3_close, @@ -6953,7 +7546,7 @@ const device_t s3_elsa_winner2000_pro_x_964_vlb_device = const device_t s3_elsa_winner2000_pro_x_pci_device = { - "S3 Vision968 (ELSA Winner 2000 Pro/X) PCI", + "S3 Vision968 PCI (ELSA Winner 2000 Pro/X)", DEVICE_PCI, S3_ELSAWIN2KPROX, s3_init, @@ -6965,21 +7558,6 @@ const device_t s3_elsa_winner2000_pro_x_pci_device = s3_968_config }; -const device_t s3_elsa_winner2000_pro_x_vlb_device = -{ - "S3 Vision968 (ELSA Winner 2000 Pro/X) VLB", - DEVICE_VLB, - S3_ELSAWIN2KPROX, - s3_init, - s3_close, - NULL, - { s3_elsa_winner2000_pro_x_available }, - s3_speed_changed, - s3_force_redraw, - s3_968_config -}; - - const device_t s3_trio64v2_dx_pci_device = { "S3 Trio64V2/DX PCI", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 46ea13292..f4a7d38ee 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -53,7 +53,6 @@ static const VIDEO_CARD video_cards[] = { { "none", NULL }, { "internal", NULL }, - { "ami_s3_924", &s3_ami_86c924_isa_device }, { "egawonder800", &atiega_device }, { "mach64gx_isa", &mach64gx_isa_device }, { "ati28800k", &ati28800k_device }, @@ -79,7 +78,6 @@ video_cards[] = { { "compaq_cga", &compaq_cga_device }, { "compaq_cga_2", &compaq_cga_2_device }, { "compaq_ega", &cpqega_device }, - { "stealthvram_isa", &s3_diamond_stealth_vram_isa_device }, { "ega", &ega_device }, { "g2_gc205", &g2_gc205_device }, { "hercules", &hercules_device }, @@ -90,13 +88,11 @@ video_cards[] = { { "kasan16vga", &et4000_kasan_isa_device }, { "mda", &mda_device }, { "genius", &genius_device }, - { "metheus928_isa", &s3_metheus_86c928_isa_device }, { "nga", &nga_device }, { "ogc", &ogc_device }, { "oti037c", &oti037c_device }, { "oti067", &oti067_device }, { "oti077", &oti077_device }, - { "orchid_s3_911", &s3_orchid_86c911_isa_device }, { "pvga1a", ¶dise_pvga1a_device }, { "wd90c11", ¶dise_wd90c11_device }, { "wd90c30", ¶dise_wd90c30_device }, @@ -104,8 +100,13 @@ video_cards[] = { { "pgc", &pgc_device }, { "radius_isa", &radius_svga_multiview_isa_device }, { "rtg3106", &realtek_rtg3106_device }, + { "stealthvram_isa", &s3_diamond_stealth_vram_isa_device }, + { "orchid_s3_911", &s3_orchid_86c911_isa_device }, + { "ami_s3_924", &s3_ami_86c924_isa_device }, + { "metheus928_isa", &s3_metheus_86c928_isa_device }, + { "px_86c801_isa", &s3_phoenix_86c801_isa_device }, + { "px_s3_v7_801_isa", &s3_spea_mirage_86c801_isa_device }, { "sigma400", &sigma_device }, - { "px_s3_v7_801_isa", &s3_v7mirage_86c801_isa_device }, { "tvga8900b", &tvga8900b_device }, { "tvga8900d", &tvga8900d_device }, { "tvga9000b", &tvga9000b_device }, @@ -135,28 +136,30 @@ video_cards[] = { { "cl_gd5480_pci", &gd5480_pci_device }, { "ctl3d_banshee_pci", &creative_voodoo_banshee_device }, { "stealth32_pci", &et4000w32p_pci_device }, + { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, + { "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device }, + { "bahamas64_pci", &s3_bahamas64_pci_device }, + { "px_vision864_pci", &s3_phoenix_vision864_pci_device }, + { "stealthse_pci", &s3_diamond_stealth_se_pci_device }, + { "px_trio32_pci", &s3_phoenix_trio32_pci_device }, + { "stealth64d_pci", &s3_diamond_stealth64_pci_device }, + { "n9_9fx_pci", &s3_9fx_pci_device }, + { "px_trio64_pci", &s3_phoenix_trio64_pci_device }, + { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, + { "mirovideo40sv_pci", &s3_mirovideo_40sv_968_pci_device }, + { "spea_mercury64p_pci", &s3_spea_mercury_p64v_pci_device }, + { "px_vision868_pci", &s3_phoenix_vision868_pci_device }, + { "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, + { "trio64v2dx_pci", &s3_trio64v2_dx_pci_device }, { "stealth3d_2000_pci", &s3_virge_pci_device }, { "stealth3d_3000_pci", &s3_virge_988_pci_device }, - { "stealth64d_pci", &s3_diamond_stealth64_pci_device }, - { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, - { "stealthse_pci", &s3_diamond_stealth_se_pci_device }, - { "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device }, - { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, #if defined(DEV_BRANCH) && defined(USE_MGA) { "mystique", &mystique_device }, { "mystique_220", &mystique_220_device }, #endif - { "n9_9fx_pci", &s3_9fx_pci_device }, - { "bahamas64_pci", &s3_bahamas64_pci_device }, - { "px_vision864_pci", &s3_phoenix_vision864_pci_device }, - { "px_vision868_pci", &s3_phoenix_vision868_pci_device }, - { "px_trio32_pci", &s3_phoenix_trio32_pci_device }, - { "px_trio64_pci", &s3_phoenix_trio64_pci_device }, - { "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, #if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) { "trio3d2x", &s3_trio3d_2x_pci_device }, #endif - { "trio64v2dx_pci", &s3_trio64v2_dx_pci_device }, { "virge325_pci", &s3_virge_325_pci_device }, { "virge375_pci", &s3_virge_375_pci_device }, { "virge375_vbe20_pci", &s3_virge_375_4_pci_device }, @@ -181,21 +184,20 @@ video_cards[] = { { "cl_gd5430_vlb", &gd5430_vlb_device }, { "stealth3d_2000_vlb", &s3_virge_vlb_device }, { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, - { "stealth64d_vlb", &s3_diamond_stealth64_vlb_device }, - { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, - { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, - { "elsawin2kprox_964_vlb", &s3_elsa_winner2000_pro_x_964_vlb_device }, - { "elsawin2kprox_vlb", &s3_elsa_winner2000_pro_x_vlb_device }, - { "ht216_32", &ht216_32_standalone_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, - { "n9_9fx_vlb", &s3_9fx_vlb_device }, - { "bahamas64_vlb", &s3_bahamas64_vlb_device }, + { "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device }, { "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, + { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, + { "bahamas64_vlb", &s3_bahamas64_vlb_device }, { "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, - { "px_vision868_vlb", &s3_phoenix_vision868_vlb_device }, + { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, { "px_trio32_vlb", &s3_phoenix_trio32_vlb_device }, + { "stealth64d_vlb", &s3_diamond_stealth64_vlb_device }, + { "n9_9fx_vlb", &s3_9fx_vlb_device }, { "px_trio64_vlb", &s3_phoenix_trio64_vlb_device }, - { "px_trio64vplus_vlb", &s3_phoenix_trio64vplus_vlb_device }, + { "spea_miragep64_vlb", &s3_spea_mirage_p64_vlb_device }, + { "px_vision868_vlb", &s3_phoenix_vision868_vlb_device }, + { "ht216_32", &ht216_32_standalone_device }, { "virge325_vlb", &s3_virge_325_vlb_device }, { "virge375_vlb", &s3_virge_375_vlb_device }, { "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device }, diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 642991b58..dfce72e06 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -117,6 +117,7 @@ typedef struct tgui_t int16_t dst_x, dst_y; int16_t dst_y_clip, dst_x_clip; int16_t size_x, size_y; + uint16_t sv_size_y; uint16_t patloc; uint32_t fg_col, bg_col; uint32_t style, ckey; @@ -133,7 +134,7 @@ typedef struct tgui_t int pat_x, pat_y; int use_src; - int src_pitch, dst_pitch, bpp; + int pitch, bpp; uint32_t fill_pattern[8*8]; uint32_t mono_pattern[8*8]; uint32_t pattern_8[8*8]; @@ -146,8 +147,9 @@ typedef struct tgui_t uint8_t tgui_3d8, tgui_3d9; int oldmode; - uint8_t oldctrl1; - uint8_t oldctrl2,newctrl2; + uint8_t oldctrl1, newctrl1; + uint8_t oldctrl2, newctrl2; + uint8_t oldgr0e, newgr0e; uint32_t linear_base, linear_size, ge_base, mmio_base; @@ -296,23 +298,21 @@ tgui_out(uint16_t addr, uint8_t val, void *p) { tgui_t *tgui = (tgui_t *)p; svga_t *svga = &tgui->svga; - uint8_t old, mask; - - mask = (tgui->type >= TGUI_9660) ? 0x3f : 0x1f; + uint8_t old; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { case 0x3C5: - switch (svga->seqaddr & 0xf) + switch (svga->seqaddr) { case 0xB: - tgui->oldmode=1; + tgui->oldmode = 1; break; case 0xC: - if (svga->seqregs[0xe] & 0x80) - svga->seqregs[0xc] = val; + if (svga->seqregs[0x0e] & 0x80) + svga->seqregs[0x0c] = val; break; case 0xd: if (tgui->oldmode) @@ -324,12 +324,13 @@ tgui_out(uint16_t addr, uint8_t val, void *p) if (tgui->oldmode) { tgui->oldctrl1 = val; tgui_update_irqs(tgui); - } else { - svga->seqregs[0xe] = (val ^ 2); - svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; - if (!(svga->gdcreg[0xf] & 1)) - svga->read_bank = svga->write_bank; + svga->write_bank = (tgui->oldctrl1) * 65536; + } else { + svga->seqregs[0xe] = val ^ 2; + svga->write_bank = (svga->seqregs[0xe]) * 65536; } + if (!(svga->gdcreg[0xf] & 1)) + svga->read_bank = svga->write_bank; return; } break; @@ -344,16 +345,16 @@ tgui_out(uint16_t addr, uint8_t val, void *p) { tgui->ramdac_state = 0; tgui->ramdac_ctrl = val; - switch (tgui->ramdac_ctrl & 0xf0) + switch ((tgui->ramdac_ctrl >> 4) & 0x0f) { - case 0x10: + case 1: svga->bpp = 15; break; - case 0x30: + case 3: svga->bpp = 16; break; - case 0xd0: - svga->bpp = ((svga->crtc[0x38] & 0x08) == 0x08 && (tgui->type == TGUI_9440)) ? 24 : 32; + case 0x0d: + svga->bpp = (tgui->type >= TGUI_9660) ? 32 : 24; break; default: svga->bpp = 8; @@ -370,7 +371,7 @@ tgui_out(uint16_t addr, uint8_t val, void *p) tkd8001_ramdac_out(addr, val, svga->ramdac, svga); return; } - tgui->ramdac_state = 0; + tgui->ramdac_state = 0; break; case 0x3CF: @@ -387,26 +388,45 @@ tgui_out(uint16_t addr, uint8_t val, void *p) tgui_recalcmapping(tgui); return; } - switch (svga->gdcaddr & 15) + switch (svga->gdcaddr) { - case 0x6: - if (svga->gdcreg[6] != val) - { - svga->gdcreg[6] = val; - tgui_recalcmapping(tgui); - } - return; + case 0x6: + if (svga->gdcreg[6] != val) + { + svga->gdcreg[6] = val; + tgui_recalcmapping(tgui); + } + return; - case 0xE: + case 0x0e: svga->gdcreg[0xe] = val ^ 2; if ((svga->gdcreg[0xf] & 1) == 1) - svga->read_bank = (svga->gdcreg[0xe] & 0xf) * 65536; + svga->read_bank = (svga->gdcreg[0xe]) * 65536; break; - case 0xF: - if (val & 1) svga->read_bank = (svga->gdcreg[0xe] & 0xf) *65536; - else svga->read_bank = (svga->seqregs[0xe] & 0xf) *65536; - svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; + case 0x0f: + if (val & 1) + svga->read_bank = (svga->gdcreg[0xe]) * 65536; + else { + if (tgui->oldmode) + svga->read_bank = (tgui->oldctrl1) * 65536; + else + svga->read_bank = (svga->seqregs[0xe]) * 65536; + } + + if (tgui->oldmode) + svga->write_bank = (tgui->oldctrl1) * 65536; + else + svga->write_bank = (svga->seqregs[0xe]) * 65536; break; + + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + svga->gdcreg[svga->gdcaddr] = val; + break; } break; case 0x3D4: @@ -434,7 +454,7 @@ tgui_out(uint16_t addr, uint8_t val, void *p) } } switch (svga->crtcreg) { - case 0x1e: + case 0x1e: svga->vram_display_mask = (val & 0x80) ? tgui->vram_mask : 0x3ffff; break; @@ -445,6 +465,7 @@ tgui_out(uint16_t addr, uint8_t val, void *p) tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000; svga->decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff; } + pclog("Linear base = %08x, size = %08x, mask = %08x\n", tgui->linear_base, tgui->linear_size, svga->decode_mask); tgui_recalcmapping(tgui); } break; @@ -461,11 +482,6 @@ tgui_out(uint16_t addr, uint8_t val, void *p) case 0x39: tgui_recalcmapping(tgui); break; - - case 0x37: - if (tgui->type >= TGUI_9660) - i2c_gpio_set(tgui->i2c, !!(val & 0x02), (val & 0x01)); - break; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: @@ -490,19 +506,20 @@ tgui_out(uint16_t addr, uint8_t val, void *p) } return; - case 0x3D8: - tgui->tgui_3d8 = val; - if (svga->gdcreg[0xf] & 4) { - svga->write_bank = (val & mask) * 65536; - if (!(svga->gdcreg[0xf] & 1)) - svga->read_bank = (val & mask) * 65536; - } - return; + case 0x3D8: + tgui->tgui_3d8 = val; + if (svga->gdcreg[0xf] & 4) { + svga->write_bank = (val & 0x3f) * 65536; + if (!(svga->gdcreg[0xf] & 1)) { + svga->read_bank = (val & 0x3f) * 65536; + } + } + return; case 0x3D9: - tgui->tgui_3d9 = val; - if ((svga->gdcreg[0xf] & 5) == 5) - svga->read_bank = (val & mask) * 65536; - return; + tgui->tgui_3d9 = val; + if ((svga->gdcreg[0xf] & 5) == 5) + svga->read_bank = (val & 0x3f) * 65536; + return; case 0x43c8: tgui->clock_n = val & 0x7f; @@ -528,11 +545,11 @@ tgui_in(uint16_t addr, void *p) switch (addr) { case 0x3C5: - if ((svga->seqaddr & 0xf) == 9) { + if (svga->seqaddr == 9) { if (tgui->type == TGUI_9680) return 0x01; /*TGUI9680XGi*/ } - if ((svga->seqaddr & 0xf) == 0xb) + if (svga->seqaddr == 0x0b) { tgui->oldmode = 0; switch (tgui->type) @@ -546,16 +563,22 @@ tgui_in(uint16_t addr, void *p) return 0xd3; /*TGUI9660XGi*/ } } - if ((svga->seqaddr & 0xf) == 0xd) + if (svga->seqaddr == 0x0d) { if (tgui->oldmode) return tgui->oldctrl2; return tgui->newctrl2; } - if ((svga->seqaddr & 0xf) == 0xe) + if (svga->seqaddr == 0x0c) + { + if (svga->seqregs[0x0e] & 0x80) + return svga->seqregs[0x0c]; + } + if (svga->seqaddr == 0x0e) { if (tgui->oldmode) - return tgui->oldctrl1; + return tgui->oldctrl1 | 0x88; + return svga->seqregs[0x0e]; } break; @@ -576,19 +599,13 @@ tgui_in(uint16_t addr, void *p) case 0x3CF: if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) return tgui->ext_gdc_regs[svga->gdcaddr & 15]; - break; + if (svga->gdcaddr >= 0x5a && svga->gdcaddr <= 0x5f) + return svga->gdcreg[svga->gdcaddr]; + break; case 0x3D4: return svga->crtcreg; case 0x3D5: temp = svga->crtc[svga->crtcreg]; - if (svga->crtcreg == 0x37) { - if (tgui->type >= TGUI_9660) { - if ((svga->crtc[0x37] & 0x02) && i2c_gpio_get_scl(tgui->i2c)) - temp |= 0x02; - if ((svga->crtc[0x37] & 0x01) && i2c_gpio_get_sda(tgui->i2c)) - temp |= 0x01; - } - } return temp; case 0x3d8: return tgui->tgui_3d8; @@ -615,14 +632,17 @@ void tgui_recalctimings(svga_t *svga) svga->rowoffset <<= 1; } - if ((svga->crtc[0x1e] & 0xa0) == 0xa0) + + + if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; - if (svga->crtc[0x27] & 0x01) + if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000; - if (svga->crtc[0x27] & 0x02) + if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000; - if (svga->crtc[0x27] & 0x04) + if ((svga->crtc[0x27] & 0x04) == 0x04) svga->ma_latch |= 0x80000; + if (svga->crtc[0x27] & 0x08) svga->split |= 0x400; if (svga->crtc[0x27] & 0x10) @@ -639,7 +659,7 @@ void tgui_recalctimings(svga_t *svga) svga->lowres = 0; } - if (((tgui->oldctrl2 & 0x10) && (svga->crtc[0x1e] & 0x20) && (tgui->oldctrl1 & 1)) || (svga->crtc[0x2a] & 0x40)) /*According to vgadoc*/ + if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) svga->ma_latch <<= 1; svga->lowres = !(svga->crtc[0x2a] & 0x40); @@ -715,6 +735,11 @@ void tgui_recalctimings(svga_t *svga) break; case 32: svga->render = svga_render_32bpp_highres; + if (tgui->type >= TGUI_9660) { + if (svga->hdisp == 1024) { + svga->rowoffset <<= 1; + } + } break; } } @@ -892,7 +917,7 @@ uint8_t tgui_pci_read(int func, int addr, void *p) case 0x02: return (tgui->type == TGUI_9440) ? 0x40 : 0x60; /*TGUI9440AGi or TGUI9660XGi*/ case 0x03: return (tgui->type == TGUI_9440) ? 0x94 : 0x96; - case PCI_REG_COMMAND: return tgui->pci_regs[PCI_REG_COMMAND] & 0x23; /*Respond to IO and memory accesses*/ + case PCI_REG_COMMAND: return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -946,7 +971,6 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p) tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16); tgui->linear_size = tgui->vram_size; svga->decode_mask = tgui->vram_mask; - svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4); tgui_recalcmapping(tgui); break; case 0x13: @@ -956,7 +980,6 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p) tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24); tgui->linear_size = tgui->vram_size; svga->decode_mask = tgui->vram_mask; - svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6); tgui_recalcmapping(tgui); break; @@ -1210,7 +1233,8 @@ enum { TGUI_BITBLT = 1, TGUI_SCANLINE = 3, - TGUI_BRESENHAMLINE = 4 + TGUI_BRESENHAMLINE = 4, + TGUI_SHORTVECTOR = 5 }; enum @@ -1339,62 +1363,88 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } /*Other than mode stuff, this bit is undocumented*/ + pclog("TGUI ger22 = %04x, cmd = %i, hdisp = %i, svga = %i, bpp = %i\n", tgui->accel.ger22, tgui->accel.command, svga->hdisp, svga->bpp, tgui->accel.bpp); switch (tgui->accel.ger22 & 0xff) { + case 0: + switch (tgui->accel.ger22 >> 8) { + case 0x41: + tgui->accel.pitch = 640; + break; + } + break; + case 4: - tgui->accel.src_pitch = 1024; - tgui->accel.dst_pitch = 1024; - if (svga->hdisp == 800) { - if ((tgui->accel.ger22 >> 8) > 0) { - tgui->accel.src_pitch = 832; - tgui->accel.dst_pitch = 832; - } - } - break; - - case 8: - tgui->accel.src_pitch = 2048; - tgui->accel.dst_pitch = 2048; - if (tgui->type >= TGUI_9660) { - tgui->accel.src_pitch = 1280; - tgui->accel.dst_pitch = 1280; - } - break; - - case 9: - tgui->accel.src_pitch = 1024; - tgui->accel.dst_pitch = 1024; - if (tgui->type >= TGUI_9660) { - tgui->accel.src_pitch = svga->hdisp; - tgui->accel.dst_pitch = svga->hdisp; - if (svga->hdisp == 800) { - tgui->accel.src_pitch = 832; - tgui->accel.dst_pitch = 832; - } - } - break; - - case 14: - tgui->accel.src_pitch = svga->hdisp; - tgui->accel.dst_pitch = svga->hdisp; - switch (tgui->svga.bpp) { - case 32: - if (svga->hdisp == 800) { - tgui->accel.src_pitch = 832; - tgui->accel.dst_pitch = 832; + switch (tgui->accel.ger22 >> 8) { + case 0: + tgui->accel.pitch = 1024; + break; + case 0x40: + tgui->accel.pitch = 640; + break; + case 0x50: + tgui->accel.pitch = 832; + break; + } + break; + case 8: + switch (tgui->accel.ger22 >> 8) { + case 0: + tgui->accel.pitch = 2048; + break; + case 0x60: + tgui->accel.pitch = 1280; + break; + } + break; + case 9: + switch (tgui->accel.ger22 >> 8) { + case 0: + tgui->accel.pitch = svga->hdisp; + if (tgui->type == TGUI_9440) + tgui->accel.pitch = 1024; + break; + case 0x40: + tgui->accel.pitch = 640; + break; + case 0x50: + tgui->accel.pitch = 832; + break; + } + break; + case 13: + switch (tgui->accel.ger22 >> 8) { + case 0x60: + tgui->accel.pitch = 2048; + if (tgui->type >= TGUI_9660) { + if (svga->hdisp == 1280) + tgui->accel.pitch = svga->hdisp; + } + break; + } + break; + case 14: + switch (tgui->accel.ger22 >> 8) { + case 0: + tgui->accel.pitch = 1024; + break; + case 0x40: + tgui->accel.pitch = 640; + break; + case 0x50: + tgui->accel.pitch = 832; + break; } break; - } - break; } switch (tgui->accel.command) { case TGUI_BITBLT: if (count == -1) { - tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.src_pitch); + tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); tgui->accel.src = tgui->accel.src_old; - tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.dst_pitch); + tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); tgui->accel.dst = tgui->accel.dst_old; tgui->accel.pat_x = tgui->accel.dst_x; @@ -1479,8 +1529,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) tgui->accel.dy += ydir; } - tgui->accel.src_old += (ydir * tgui->accel.src_pitch); - tgui->accel.dst_old += (ydir * tgui->accel.dst_pitch); + tgui->accel.src_old += (ydir * tgui->accel.pitch); + tgui->accel.dst_old += (ydir * tgui->accel.pitch); tgui->accel.src = tgui->accel.src_old; tgui->accel.dst = tgui->accel.dst_old; @@ -1541,8 +1591,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) tgui->accel.pat_x = tgui->accel.dst_x; tgui->accel.pat_y += ydir; - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.src_pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.dst_pitch); + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); tgui->accel.y++; @@ -1588,8 +1638,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) tgui->accel.pat_x = tgui->accel.dst_x; tgui->accel.pat_y += ydir; - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.src_pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.dst_pitch); + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); if (tgui->accel.y > tgui->accel.size_y) return; @@ -1602,10 +1652,10 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) case TGUI_SCANLINE: { if (count == -1) { - tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.src_pitch); + tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); tgui->accel.src = tgui->accel.src_old; - tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.dst_pitch); + tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); tgui->accel.dst = tgui->accel.dst_old; tgui->accel.pat_x = tgui->accel.dst_x; @@ -1639,8 +1689,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) tgui->accel.x = 0; tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.src_pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.dst_pitch); + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); tgui->accel.pat_y += ydir; return; } @@ -1697,13 +1747,13 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } while (count--) { - READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.src_pitch), src_dat); + READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ if (steep) { if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right && dy >= tgui->accel.top && dy <= tgui->accel.bottom)) { - READ(dx + (dy * tgui->accel.dst_pitch), dst_dat); + READ(dx + (dy * tgui->accel.pitch), dst_dat); pat_dat = tgui->accel.fg_col; @@ -1714,12 +1764,12 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) MIX(); - WRITE(dx + (dy * tgui->accel.dst_pitch), out); + WRITE(dx + (dy * tgui->accel.pitch), out); } } else { if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dy >= tgui->accel.left && dy <= tgui->accel.right && - dx >= tgui->accel.top && dx <= tgui->accel.bottom)) { - READ(dy + (dx * tgui->accel.dst_pitch), dst_dat); + dx >= tgui->accel.top && dx <= tgui->accel.bottom)) { + READ(dy + (dx * tgui->accel.pitch), dst_dat); pat_dat = tgui->accel.fg_col; @@ -1730,7 +1780,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) MIX(); - WRITE(dy + (dx * tgui->accel.dst_pitch), out); + WRITE(dy + (dx * tgui->accel.pitch), out); } } @@ -1748,13 +1798,92 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } } break; + + case TGUI_SHORTVECTOR: + { + int16_t dx, dy; + + dx = tgui->accel.dst_x & 0xfff; + dy = tgui->accel.dst_y & 0xfff; + + tgui->accel.left = tgui->accel.src_x_clip & 0xfff; + tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; + tgui->accel.top = tgui->accel.src_y_clip & 0xfff; + tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; + + if (tgui->accel.bpp == 1) { + tgui->accel.left >>= 1; + tgui->accel.right >>= 1; + } else if (tgui->accel.bpp == 3) { + tgui->accel.left >>= 2; + tgui->accel.right >>= 2; + } + + while (count--) { + READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); + + /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right && + dy >= tgui->accel.top && dy <= tgui->accel.bottom)) { + READ(dx + (dy * tgui->accel.pitch), dst_dat); + + pat_dat = tgui->accel.fg_col; + + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; + + MIX(); + + WRITE(dx + (dy * tgui->accel.pitch), out); + } + + if (tgui->accel.y == (tgui->accel.sv_size_y & 0xfff)) + break; + + switch ((tgui->accel.sv_size_y >> 8) & 0xe0) { + case 0x00: + dx++; + break; + case 0x20: + dx++; + dy--; + break; + case 0x40: + dy--; + break; + case 0x60: + dx--; + dy--; + break; + case 0x80: + dx--; + break; + case 0xa0: + dx--; + dy++; + break; + case 0xc0: + dy++; + break; + case 0xe0: + dx++; + dy++; + break; + } + + tgui->accel.y++; + } + } + break; } } static void tgui_accel_out(uint16_t addr, uint8_t val, void *p) { - tgui_t *tgui = (tgui_t *)p; + tgui_t *tgui = (tgui_t *)p; switch (addr) { @@ -1770,6 +1899,7 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *p) tgui->accel.bpp = 1; break; + case 13: case 14: switch (tgui->svga.bpp) { case 15: @@ -1891,9 +2021,11 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *p) break; case 0x2142: /*Size Y*/ tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; + tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val; break; case 0x2143: /*Size Y*/ tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); + tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8); break; case 0x2144: /*Style*/ @@ -2192,8 +2324,8 @@ tgui_accel_in_l(uint16_t addr, void *p) static void tgui_accel_write(uint32_t addr, uint8_t val, void *p) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; if ((svga->crtc[0x36] & 0x03) == 0x02) { if ((addr & ~0xff) != 0xbff00) @@ -2217,6 +2349,7 @@ tgui_accel_write(uint32_t addr, uint8_t val, void *p) tgui->accel.bpp = 1; break; + case 13: case 14: switch (tgui->svga.bpp) { case 15: @@ -2338,9 +2471,11 @@ tgui_accel_write(uint32_t addr, uint8_t val, void *p) break; case 0x42: /*Size Y*/ tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; + tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val; break; case 0x43: /*Size Y*/ tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); + tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8); break; case 0x44: /*Style*/ @@ -2905,11 +3040,6 @@ void tgui_close(void *p) svga_close(&tgui->svga); - if (tgui->type >= TGUI_9660) { - ddc_close(tgui->ddc); - i2c_gpio_close(tgui->i2c); - } - free(tgui); } diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/vid_tvp3026_ramdac.c new file mode 100644 index 000000000..926921946 --- /dev/null +++ b/src/video/vid_tvp3026_ramdac.c @@ -0,0 +1,472 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Texas Instruments TVP3026 true colour RAMDAC + * family. + * + * + * TODO: Clock and other parts. + * + * Authors: TheCollector1995, + * + * Copyright 2021 TheCollector1995. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> + + +typedef struct +{ + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t cursor64_data[1024]; + int hwc_y, hwc_x; + uint8_t ind_idx; + uint8_t dcc, dc_init; + uint8_t ccr; + uint8_t true_color; + uint8_t latch_cntl; + uint8_t mcr; + uint8_t ppr; + uint8_t general_cntl; + uint8_t mclk; + uint8_t misc; + uint8_t type; + uint8_t mode; +} tvp3026_ramdac_t; + +static void +tvp3026_set_bpp(tvp3026_ramdac_t *ramdac, svga_t *svga) +{ + if ((ramdac->true_color & 0x80) == 0x80) { + if (ramdac->mcr & 0x08) + svga->bpp = 8; + else + svga->bpp = 4; + } else { + switch (ramdac->true_color & 0x0f) { + case 0x01: + case 0x03: + case 0x05: + svga->bpp = 16; + break; + case 0x04: + svga->bpp = 15; + break; + case 0x06: + case 0x07: + if (ramdac->true_color & 0x10) + svga->bpp = 24; + else + svga->bpp = 32; + break; + case 0x0e: + case 0x0f: + svga->bpp = 24; + break; + } + } + svga_recalctimings(svga); +} + + +void +tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga) +{ + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p; + uint32_t o32; + uint8_t *cd; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + rs |= (!!rs2 << 2); + rs |= (!!rs3 << 3); + + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + ramdac->ind_idx = val; + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + case 0x03: + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + svga->dac_status = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 3; + ramdac->extpal[index].r = svga->dac_r; + ramdac->extpal[index].g = svga->dac_g; + ramdac->extpal[index].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b); + else + ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]); + + if (svga->ext_overscan && !index) { + o32 = svga->overscan_color; + svga->overscan_color = ramdac->extpallook[0]; + if (o32 != svga->overscan_color) + svga_recalctimings(svga); + } + svga->dac_addr = (svga->dac_addr + 1) & 0xff; + svga->dac_pos = 0; + break; + } + break; + case 0x09: /* Direct Cursor Control (RS value = 1001) */ + ramdac->dcc = val; + if (ramdac->ccr & 0x80) { + svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; + svga->dac_hwcursor.ena = ((val & 0x03) != 0); + ramdac->mode = val & 0x03; + } + break; + case 0x0a: /* Indexed Data (RS value = 1010) */ + switch (ramdac->ind_idx) { + case 0x06: /* Indirect Cursor Control */ + ramdac->ccr = val; + svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; + svga->dac_hwcursor.ena = ((val & 0x03) != 0); + ramdac->mode = val & 0x03; + break; + case 0x0f: /* Latch Control */ + ramdac->latch_cntl = val; + break; + case 0x18: /* True Color Control */ + ramdac->true_color = val; + tvp3026_set_bpp(ramdac, svga); + break; + case 0x19: /* Multiplex Control */ + ramdac->mcr = val; + tvp3026_set_bpp(ramdac, svga); + break; + case 0x1c: /* Palette-Page Register */ + ramdac->ppr = val; + break; + case 0x1d: /* General Control Register */ + ramdac->general_cntl = val; + break; + case 0x1e: /* Miscellaneous Control */ + ramdac->misc = val; + svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT; + break; + case 0x39: /* MCLK/Loop Clock Control */ + ramdac->mclk = val; + break; + + } + break; + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + index = svga->dac_addr & da_mask; + cd = (uint8_t *) ramdac->cursor64_data; + cd[index] = val; + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; + break; + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8); + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; + break; + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; + break; + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8); + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; + break; + } + + return; +} + + +uint8_t +tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga) +{ + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p; + uint8_t temp = 0xff; + uint8_t *cd; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + rs |= (!!rs2 << 2); + rs |= (!!rs3 << 3); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + temp = svga_in(addr, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + temp = svga->dac_addr & 0xff; + break; + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + index = (svga->dac_addr - 1) & 3; + svga->dac_status = 3; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].r; + else + temp = ramdac->extpal[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].g; + else + temp = ramdac->extpal[index].g & 0x3f; + break; + case 2: + svga->dac_pos=0; + svga->dac_addr = svga->dac_addr + 1; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].b; + else + temp = ramdac->extpal[index].b & 0x3f; + break; + } + break; + case 0x09: /* Direct Cursor Control (RS value = 1001) */ + temp = ramdac->dcc; + break; + case 0x0a: /* Indexed Data (RS value = 1010) */ + switch (ramdac->ind_idx) { + case 0x01: /* Silicon Revision */ + temp = 0x00; + break; + case 0x06: /* Indirect Cursor Control */ + temp = ramdac->ccr; + break; + case 0x0f: /* Latch Control */ + temp = ramdac->latch_cntl; + break; + case 0x18: /* True Color Control */ + temp = ramdac->true_color; + break; + case 0x19: /* Multiplex Control */ + temp = ramdac->mcr; + break; + case 0x1c: /* Palette-Page Register */ + temp = ramdac->ppr; + break; + case 0x1d: /* General Control Register */ + temp = ramdac->general_cntl; + break; + case 0x1e: /* Miscellaneous Control */ + temp = ramdac->misc; + break; + case 0x39: /* MCLK/Loop Clock Control */ + temp = ramdac->mclk; + break; + case 0x3f: /* ID */ + temp = 0x26; + break; + } + break; + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + index = (svga->dac_addr - 1) & da_mask; + cd = (uint8_t *) ramdac->cursor64_data; + temp = cd[index]; + + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + temp = ramdac->hwc_x & 0xff; + break; + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + temp = (ramdac->hwc_x >> 8) & 0xff; + break; + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + temp = ramdac->hwc_y & 0xff; + break; + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + temp = (ramdac->hwc_y >> 8) & 0xff; + break; + } + + return temp; +} + +void +tvp3026_recalctimings(void *p, svga_t *svga) +{ + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p; + + svga->interlace = (ramdac->ccr & 0x40); +} + + +void +tvp3026_hwcursor_draw(svga_t *svga, int displine) +{ + int x, xx, comb, b0, b1; + uint16_t dat[2]; + int offset = svga->dac_hwcursor_latch.x + svga->dac_hwcursor_latch.xoff; + int pitch, bppl, mode, x_pos, y_pos; + uint32_t clr1, clr2, clr3, *p; + uint8_t *cd; + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) svga->ramdac; + + clr1 = ramdac->extpallook[1]; + clr2 = ramdac->extpallook[2]; + clr3 = ramdac->extpallook[3]; + + /* The planes come in two parts, and each plane is 1bpp, + so a 32x32 cursor has 4 bytes per line, and a 64x64 + cursor has 8 bytes per line. */ + pitch = (svga->dac_hwcursor_latch.xsize >> 3); /* Bytes per line. */ + /* A 32x32 cursor has 128 bytes per line, and a 64x64 + cursor has 512 bytes per line. */ + bppl = (pitch * svga->dac_hwcursor_latch.ysize); /* Bytes per plane. */ + mode = ramdac->mode; + + if (svga->interlace && svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; + + cd = (uint8_t *) ramdac->cursor64_data; + + for (x = 0; x < svga->dac_hwcursor_latch.xsize; x += 16) { + dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | + cd[svga->dac_hwcursor_latch.addr + 1]; + dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | + cd[svga->dac_hwcursor_latch.addr + bppl + 1]; + + for (xx = 0; xx < 16; xx++) { + b0 = (dat[0] >> (15 - xx)) & 1; + b1 = (dat[1] >> (15 - xx)) & 1; + comb = (b0 | (b1 << 1)); + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + if (offset >= svga->dac_hwcursor_latch.x) { + switch (mode) { + case 1: /* Three Color */ + switch (comb) { + case 1: + p[x_pos] = clr1; + break; + case 2: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] = clr3; + break; + } + break; + case 2: /* XGA */ + switch (comb) { + case 0: + p[x_pos] = clr1; + break; + case 1: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + } + break; + case 3: /* X-Windows */ + switch (comb) { + case 2: + p[x_pos] = clr1; + break; + case 3: + p[x_pos] = clr2; + break; + } + break; + } + } + offset++; + } + svga->dac_hwcursor_latch.addr += 2; + } + + if (svga->interlace && !svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; +} + + +void * +tvp3026_ramdac_init(const device_t *info) +{ + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) malloc(sizeof(tvp3026_ramdac_t)); + memset(ramdac, 0, sizeof(tvp3026_ramdac_t)); + + ramdac->type = info->local; + + ramdac->latch_cntl = 0x06; + ramdac->true_color = 0x80; + ramdac->mcr = 0x98; + ramdac->mclk = 0x18; + + return ramdac; +} + + +static void +tvp3026_ramdac_close(void *priv) +{ + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; + + if (ramdac) + free(ramdac); +} + + +const device_t tvp3026_ramdac_device = +{ + "TI TVP3026 RAMDAC", + 0, 0, + tvp3026_ramdac_init, tvp3026_ramdac_close, + NULL, { NULL }, NULL, NULL +}; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index 519b86923..a9b0e52c9 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -1237,23 +1237,7 @@ void *voodoo_init() void voodoo_card_close(voodoo_t *voodoo) { -/* #ifndef RELEASE_BUILD - FILE *f; -#endif */ int c; - -/* #ifndef RELEASE_BUILD - f = rom_fopen("texram.dmp", "wb"); - fwrite(voodoo->tex_mem[0], voodoo->texture_size*1024*1024, 1, f); - fclose(f); - if (voodoo->dual_tmus) - { - f = rom_fopen("texram2.dmp", "wb"); - fwrite(voodoo->tex_mem[1], voodoo->texture_size*1024*1024, 1, f); - fclose(f); - } -#endif */ - voodoo->fifo_thread_run = 0; thread_set_event(voodoo->wake_fifo_thread); diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 12fc053e0..913549911 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -778,7 +778,8 @@ VIDOBJ := video.o \ vid_s3.o vid_s3_virge.o \ vid_ibm_rgb528_ramdac.o vid_sdac_ramdac.o \ vid_ogc.o \ - vid_nga.o + vid_nga.o \ + vid_tvp3026_ramdac.o VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_banshee_blitter.o \ @@ -837,7 +838,7 @@ LIBS += -static ifeq ($(AUTODEP), y) %.o: %.c @echo $< - $(CC) $(CFLAGS) $(DEPS) -c $< + @$(CC) $(CFLAGS) $(DEPS) -c $< %.o: %.cc @echo $< diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index bebad43dd..8a748fb2b 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -288,7 +288,8 @@ sdl_destroy_texture(void) void sdl_close(void) { - SDL_LockMutex(sdl_mutex); + if (sdl_mutex != NULL) + SDL_LockMutex(sdl_mutex); /* Unregister our renderer! */ video_setblit(NULL);