From 63ec44440d8c86ba9c371af9eee301eadd110d90 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Thu, 4 May 2017 19:58:38 -0500 Subject: [PATCH 01/82] Make this the experimental branch --- src/Makefile.mingw | 3 ++- src/video.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 57a504121..8e28cee03 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -22,7 +22,7 @@ PROG = 86Box # Various compile-time options. # -DROM_TRACE=0xcd800 traces ROM access from segment C800 # -DIO_TACE=0x66 traces I/O on port 0x66 -STUFF = +STUFF = -DDEV_BRANCH # Add feature selections here. # -DBUGGER adds the ISA BusBugger emulation. @@ -105,6 +105,7 @@ VIDOBJ = video.o \ vid_hercules.o vid_herculesplus.o vid_incolor.o \ vid_colorplus.o \ vid_genius.o \ + vid_nv_riva128.o \ vid_s3.o vid_s3_virge.o \ vid_et4000.o vid_et4000w32.o vid_icd2061.o \ vid_oti067.o \ diff --git a/src/video.c b/src/video.c index 1176824ee..48fd4ff16 100644 --- a/src/video.c +++ b/src/video.c @@ -89,6 +89,10 @@ static VIDEO_CARD video_cards[] = {"MDA", "mda", &mda_device, GFX_MDA}, {"MDSI Genius", "genius", &genius_device, GFX_GENIUS}, {"Number Nine 9FX (S3 Trio64)", "n9_9fx", &s3_9fx_device, GFX_N9_9FX}, +#ifdef DEV_BRANCH + {"nVidia RIVA 128", "riva128", &riva128_device, GFX_RIVA128}, + {"nVidia RIVA TNT", "rivatnt", &rivatnt_device, GFX_RIVATNT}, +#endif {"OAK OTI-067", "oti067", &oti067_device, GFX_OTI067}, {"OAK OTI-077", "oti077", &oti077_device, GFX_OTI077}, {"Paradise Bahamas 64 (S3 Vision864)", "bahamas64", &s3_bahamas64_device, GFX_BAHAMAS64}, From e8f0637b7b0cb4c35a1afa8e68b8ceb9ba844f2a Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Thu, 4 May 2017 20:11:19 -0500 Subject: [PATCH 02/82] Fixed RIVA 128 compilation --- src/vid_nv_riva128.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vid_nv_riva128.c b/src/vid_nv_riva128.c index 06c08f5c0..9f47a6c41 100644 --- a/src/vid_nv_riva128.c +++ b/src/vid_nv_riva128.c @@ -2839,7 +2839,7 @@ static void riva128_add_status_info(char *s, int max_len, void *p) static device_config_t riva128_config[] = { { - "memory", "Memory size", CONFIG_SELECTION, 4, + "memory", "Memory size", CONFIG_SELECTION, "", 4, { { "1 MB", 1 @@ -3124,7 +3124,7 @@ static void rivatnt_add_status_info(char *s, int max_len, void *p) static device_config_t rivatnt_config[] = { { - "memory", "Memory size", CONFIG_SELECTION, 16, + "memory", "Memory size", CONFIG_SELECTION, "", 16, { { "4 MB", 4 From 2790ec444e777fa6d9a039958d98e796a0b50dd8 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Thu, 4 May 2017 20:22:04 -0500 Subject: [PATCH 03/82] Fixed VBLANK interrupt on nVidia cards --- src/vid_nv_riva128.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/vid_nv_riva128.c b/src/vid_nv_riva128.c index 9f47a6c41..3d6483f77 100644 --- a/src/vid_nv_riva128.c +++ b/src/vid_nv_riva128.c @@ -1994,12 +1994,11 @@ static void riva128_nvclk_poll(void *p) riva128->nvtime += cpuclock / riva128->nvfreq; } -static void riva128_vblank_poll(void *p) +static void riva128_vblank_poll(svga_t *svga) { - riva128_t *riva128 = (riva128_t *)p; - svga_t *svga = &riva128->svga; - - if(svga->vc == svga->dispend) riva128_pmc_interrupt(24, riva128); + riva128_t *riva128 = (riva128_t *)svga->p; + + riva128_pmc_interrupt(24, riva128); } static uint8_t riva128_rma_in(uint16_t addr, void *p) @@ -2793,7 +2792,8 @@ static void *riva128_init() timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); - timer_add(riva128_vblank_poll, &riva128->svga.vidtime, TIMER_ALWAYS_ENABLED, riva128); + + riva128->svga.vblank_start = riva128_vblank_poll; return riva128; } @@ -3078,7 +3078,8 @@ static void *rivatnt_init() timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); - timer_add(riva128_vblank_poll, &riva128->svga.vidtime, TIMER_ALWAYS_ENABLED, riva128); + + riva128->svga.vblank_start = riva128_vblank_poll; return riva128; } @@ -3289,7 +3290,8 @@ static void *rivatnt2_init() timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); - timer_add(riva128_vblank_poll, &riva128->svga.vidtime, TIMER_ALWAYS_ENABLED, riva128); + + riva128->svga.vblank_start = riva128_vblank_poll; return riva128; } From aa2fdc8f6d44f21ca4f7df49449c76ceff90c882 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Wed, 7 Jun 2017 13:58:44 -0500 Subject: [PATCH 04/82] Fix up some stuff --- src/Makefile.mingw | 6 -- src/VIDEO/vid_nv_riva128.c | 184 +++---------------------------------- 2 files changed, 13 insertions(+), 177 deletions(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index a6663057d..7e493882b 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -24,13 +24,7 @@ endif # Various compile-time options. # -DROM_TRACE=0xcd800 traces ROM access from segment C800 # -DIO_TACE=0x66 traces I/O on port 0x66 -<<<<<<< HEAD STUFF = -DDEV_BRANCH -======= -ifndef STUFF -STUFF = -endif ->>>>>>> master # Add feature selections here. # -DANSI_CFG forces the config file to ANSI encoding. diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index 4d3d41b24..5b9b7a986 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -29,6 +29,7 @@ typedef struct riva128_t svga_t svga; uint8_t card_id; + int pci_card; int is_nv3t; uint16_t vendor_id; @@ -439,8 +440,12 @@ static void riva128_pmc_write(uint32_t addr, uint32_t val, void *p) switch(addr) { case 0x000100: - riva128->pmc.intr &= ~val; + { + uint32_t tmp = riva128->pmc.intr & ~val; + pci_clear_irq(riva128->pci_card, PCI_INTA); + riva128->pmc.intr = tmp; break; + } case 0x000140: riva128->pmc.intr_en = val & 3; break; @@ -457,7 +462,10 @@ static void riva128_pmc_interrupt(int num, void *p) riva128->pmc.intr |= (1 << num); - if(riva128->pmc.intr_en & 1) picint(1 << riva128->pci_regs[0x3c]); + if(riva128->pmc.intr_en & 1) + { + pci_set_irq(riva128->pci_card, PCI_INTA); + } } static uint8_t riva128_pbus_read(uint32_t addr, void *p) @@ -2777,7 +2785,7 @@ static void *riva128_init() riva128->pgraph.intr = 0; riva128->ptimer.intr = 0; - pci_add(riva128_pci_read, riva128_pci_write, riva128); + riva128->pci_card = pci_add(riva128_pci_read, riva128_pci_write, riva128); riva128->ptimer.clock_mul = 1; riva128->ptimer.clock_div = 1; @@ -2856,44 +2864,6 @@ static device_config_t riva128_config[] = } }, }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, { -1 } @@ -2929,58 +2899,6 @@ static device_config_t riva128_config[] = }, .default_int = 4 }, - { - .name = "irq", - .description = "IRQ", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "IRQ 3", - .value = 3 - }, - { - .description = "IRQ 4", - .value = 4 - }, - { - .description = "IRQ 5", - .value = 5 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "IRQ 9", - .value = 9 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { - .description = "IRQ 11", - .value = 11 - }, - { - .description = "IRQ 12", - .value = 12 - }, - { - .description = "IRQ 14", - .value = 14 - }, - { - .description = "IRQ 15", - .value = 15 - }, - { - .description = "" - } - }, - .default_int = 3 - }, { .type = -1 } @@ -3066,7 +2984,7 @@ static void *rivatnt_init() riva128->pfifo.intr = 0; riva128->pgraph.intr = 0; - pci_add(riva128_pci_read, rivatnt_pci_write, riva128); + riva128->pci_card = pci_add(riva128_pci_read, rivatnt_pci_write, riva128); //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. riva128->pramdac.m_m = 0x03; @@ -3142,44 +3060,6 @@ static device_config_t rivatnt_config[] = } }, }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, { -1 } @@ -3278,7 +3158,7 @@ static void *rivatnt2_init() riva128->pfifo.intr = 0; riva128->pgraph.intr = 0; - pci_add(riva128_pci_read, rivatnt_pci_write, riva128); + riva128->pci_card = pci_add(riva128_pci_read, rivatnt_pci_write, riva128); //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. riva128->pramdac.m_m = 0x03; @@ -3371,44 +3251,6 @@ static device_config_t rivatnt2_config[] = } }, }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, { "", "", -1 } From 5fb073a6c1c28f114b36f7fea438d4111f7cb7f8 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Wed, 14 Jun 2017 15:13:05 -0500 Subject: [PATCH 05/82] Add EDID reading --- src/VIDEO/vid_nv_riva128.c | 150 +++++++++++++++++++++++++++++++++++-- 1 file changed, 144 insertions(+), 6 deletions(-) diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index 5b9b7a986..243fd59b2 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -213,8 +213,16 @@ typedef struct riva128_t { int scl; int sda; + int busy; + unsigned addrbits; + unsigned databits; uint8_t addr; //actually 7 bits uint8_t data; + struct + { + uint8_t addr; + uint8_t edid_rom[128]; + } edid_rom; } i2c; int mtime, mfreq; @@ -2133,6 +2141,22 @@ static uint8_t riva128_in(uint16_t addr, void *p) switch(svga->crtcreg) { case 0x3e: + if(riva128->i2c.busy == 2) + { + if(riva128->i2c.addr == 0xA1) + { + pclog("RIVA 128 Read EDID %02x %02x\n", riva128->i2c.edid_rom.addr, riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr]); + riva128->i2c.data <<= 1; + riva128->i2c.data |= (riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr] & (1 << riva128->i2c.databits)) >> riva128->i2c.databits; + } + riva128->i2c.databits++; + if(riva128->i2c.databits == 8) + { + riva128->i2c.databits = 0; + riva128->i2c.edid_rom.addr++; + riva128->i2c.busy = 0; + } + } ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2); break; case 0x28: @@ -2213,8 +2237,44 @@ static void riva128_out(uint16_t addr, uint8_t val, void *p) riva128->rma.mode = val & 0xf; break; case 0x3f: + if((val & 0x20) && (riva128->i2c.sda == 0) && (val & 0x10)) + { + //I2C Start Condition. + riva128->i2c.busy = 1; + } + if((val & 0x20) && (riva128->i2c.sda == 1) && !(val & 0x10)) + { + //I2C Stop Condition. + riva128->i2c.busy = 0; + } riva128->i2c.scl = (val & 0x20) ? 1 : 0; riva128->i2c.sda = (val & 0x10) ? 1 : 0; + if(riva128->i2c.busy == 1) + { + riva128->i2c.addr <<= 1; + riva128->i2c.addr |= riva128->i2c.sda; + riva128->i2c.addrbits++; + if(riva128->i2c.addrbits = 8) + { + riva128->i2c.busy = 2; + riva128->i2c.addrbits = 0; + } + } + if(riva128->i2c.busy == 2) + { + riva128->i2c.data <<= 1; + riva128->i2c.addr |= riva128->i2c.sda; + riva128->i2c.databits++; + if(riva128->i2c.databits == 8) + { + if(riva128->i2c.addr == 0xA0) + { + pclog("RIVA 128 Write EDID Address %02x\n", riva128->i2c.data); + riva128->i2c.edid_rom.addr = riva128->i2c.data; + } + riva128->i2c.databits = 0; + } + } break; } //if(svga->crtcreg > 0x18) @@ -2777,8 +2837,6 @@ static void *riva128_init() riva128->pci_regs[0x32] = 0x0c; riva128->pci_regs[0x33] = 0x00; - riva128->pci_regs[0x3c] = device_get_config_int("irq"); - riva128->pmc.intr = 0; riva128->pbus.intr = 0; riva128->pfifo.intr = 0; @@ -2799,6 +2857,34 @@ static void *riva128_init() riva128->pramdac.nv_n = 0xc2; riva128->pramdac.nv_p = 0x0d; + riva128->i2c.addrbits = 0; + riva128->i2c.databits = 0; + + uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x08, 0x01, 0x03, 0x81, 0x32, 0x26, 0x78, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x61, 0x40, + 0x45, 0x40, 0x31, 0x40, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x00, 0xfd, 0x00, 0x01, 0xff, 0x01, 0xff, 0xff, + 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec}; + + { + int i = 0; + for(;i<128;i++) + { + riva128->i2c.edid_rom.edid_rom[i] = edid_rom[i]; + } + } + timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); @@ -2977,8 +3063,6 @@ static void *rivatnt_init() riva128->pci_regs[0x32] = 0x0c; riva128->pci_regs[0x33] = 0x00; - riva128->pci_regs[0x3c] = device_get_config_int("irq"); - riva128->pmc.intr = 0; riva128->pbus.intr = 0; riva128->pfifo.intr = 0; @@ -2995,6 +3079,34 @@ static void *rivatnt_init() riva128->pramdac.nv_n = 0xc2; riva128->pramdac.nv_p = 0x0d; + riva128->i2c.addrbits = 0; + riva128->i2c.databits = 0; + + uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x08, 0x01, 0x03, 0x81, 0x32, 0x26, 0x78, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x61, 0x40, + 0x45, 0x40, 0x31, 0x40, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x00, 0xfd, 0x00, 0x01, 0xff, 0x01, 0xff, 0xff, + 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec}; + + { + int i = 0; + for(;i<128;i++) + { + riva128->i2c.edid_rom.edid_rom[i] = edid_rom[i]; + } + } + timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); @@ -3151,8 +3263,6 @@ static void *rivatnt2_init() riva128->pci_regs[0x32] = 0x0c; riva128->pci_regs[0x33] = 0x00; - riva128->pci_regs[0x3c] = device_get_config_int("irq"); - riva128->pmc.intr = 0; riva128->pbus.intr = 0; riva128->pfifo.intr = 0; @@ -3169,6 +3279,34 @@ static void *rivatnt2_init() riva128->pramdac.nv_n = 0xc2; riva128->pramdac.nv_p = 0x0d; + riva128->i2c.addrbits = 0; + riva128->i2c.databits = 0; + + uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x08, 0x01, 0x03, 0x81, 0x32, 0x26, 0x78, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x61, 0x40, + 0x45, 0x40, 0x31, 0x40, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x00, 0xfd, 0x00, 0x01, 0xff, 0x01, 0xff, 0xff, + 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec}; + + { + int i = 0; + for(;i<128;i++) + { + riva128->i2c.edid_rom.edid_rom[i] = edid_rom[i]; + } + } + timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); From 69b72d3459745c9beff34b2b160a41a196f1304e Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Wed, 14 Jun 2017 21:32:54 -0500 Subject: [PATCH 06/82] Fix EDID --- src/VIDEO/vid_nv_riva128.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index 243fd59b2..875bebaba 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -2145,7 +2145,7 @@ static uint8_t riva128_in(uint16_t addr, void *p) { if(riva128->i2c.addr == 0xA1) { - pclog("RIVA 128 Read EDID %02x %02x\n", riva128->i2c.edid_rom.addr, riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr]); + //pclog("RIVA 128 Read EDID %02x %02x\n", riva128->i2c.edid_rom.addr, riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr]); riva128->i2c.data <<= 1; riva128->i2c.data |= (riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr] & (1 << riva128->i2c.databits)) >> riva128->i2c.databits; } @@ -2269,7 +2269,7 @@ static void riva128_out(uint16_t addr, uint8_t val, void *p) { if(riva128->i2c.addr == 0xA0) { - pclog("RIVA 128 Write EDID Address %02x\n", riva128->i2c.data); + //pclog("RIVA 128 Write EDID Address %02x\n", riva128->i2c.data); riva128->i2c.edid_rom.addr = riva128->i2c.data; } riva128->i2c.databits = 0; @@ -2859,6 +2859,7 @@ static void *riva128_init() riva128->i2c.addrbits = 0; riva128->i2c.databits = 0; + riva128->i2c.busy = 0; uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3081,6 +3082,7 @@ static void *rivatnt_init() riva128->i2c.addrbits = 0; riva128->i2c.databits = 0; + riva128->i2c.busy = 0; uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3281,6 +3283,7 @@ static void *rivatnt2_init() riva128->i2c.addrbits = 0; riva128->i2c.databits = 0; + riva128->i2c.busy = 0; uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, From dbbea37d00fec9506955a261abc7d0448fa4b2e2 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Fri, 16 Jun 2017 00:54:43 -0500 Subject: [PATCH 07/82] Fix EDID reading typo --- src/VIDEO/vid_nv_riva128.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index 875bebaba..3c0657f05 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -2254,7 +2254,7 @@ static void riva128_out(uint16_t addr, uint8_t val, void *p) riva128->i2c.addr <<= 1; riva128->i2c.addr |= riva128->i2c.sda; riva128->i2c.addrbits++; - if(riva128->i2c.addrbits = 8) + if(riva128->i2c.addrbits == 8) { riva128->i2c.busy = 2; riva128->i2c.addrbits = 0; From 6ce71f9a4fef3caab82e63c557651766ff339432 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Wed, 19 Jul 2017 23:03:49 -0500 Subject: [PATCH 08/82] Add configurability of the PCI device ID for certain nVidia cards --- src/VIDEO/vid_nv_riva128.c | 48 +++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index c4639851d..79a030d69 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -129,7 +129,7 @@ typedef struct riva128_t struct { - uint32_t boot0; + uint32_t boot_0; } pextdev; struct @@ -986,19 +986,60 @@ static uint8_t riva128_pextdev_read(uint32_t addr, void *p) //pclog("RIVA 128 PEXTDEV read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //For NV3, we give it PCI 66MHz, card mode, PCI bus type, 13.5MHz crystal, no TV encoder, and PCI 2.1. + //For NV4, we give it normal PCI line polarity, card mode, 13.5 MHz crystal, no TV encoder, and PCI bus type + switch(addr) { case 0x101000: - ret = 0x9e; + switch(riva128->card_id) + { + case 0x03: + ret = 0x13; + break; + case 0x04: + ret = 0x83; + break; + } break; case 0x101001: - ret = 0x01; + switch(riva128->card_id) + { + case 0x03: + if(!riva128->is_nv3t) ret = 0x02; + else ret = 0x00; + break; + } + case 0x04: + //Bits 12-13 of the NV4+ strap set 0 configure the GPU's PCI device ID. + ret = (riva128->pextdev.boot_0 & 0x80000000) ? (0x8f | ((riva128->pextdev.boot_0 >> 8) & 0x30)) : 0x8f; + break; + } + break; break; } return ret; } +static void riva128_pextdev_write(uint32_t addr, uint32_t val, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + //pclog("RIVA 128 PEXTDEV write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + + switch(addr) + { + case 0x101000: + riva128->pextdev.boot_0 = val; + if((val & 0x80000000) && ((riva128->card_id == 0x05) || (riva128->card_id == 0x10) || (riva128->card_id == 0x11) || (riva128->card_id == 0x15) + || (riva128->card_id == 0x1a))) + { + riva128->device_id = (riva128->device_id & 0xfffc) | ((val >> 12) & 3); + } + break; + } +} + static void rivatnt_pgraph_ctx_switch(void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -1952,6 +1993,7 @@ static void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p) if((addr >= 0x002000) && (addr <= 0x002fff)) riva128_pfifo_write(addr, val, riva128); if((addr >= 0x009000) && (addr <= 0x009fff)) riva128_ptimer_write(addr, val, riva128); if((addr >= 0x100000) && (addr <= 0x100fff)) riva128_pfb_write(addr, val, riva128); + if((addr >= 0x101000) && (addr <= 0x101fff)) riva128_pextdev_write(addr, val, riva128); if((addr >= 0x400000) && (addr <= 0x400fff)) riva128_pgraph_write(addr, val, riva128); if((addr >= 0x680000) && (addr <= 0x680fff)) riva128_pramdac_write(addr, val, riva128); if((addr >= 0x800000) && (addr <= 0xffffff)) riva128_user_write(addr, val, riva128); From 23452bd39cc015d97661740090988ddadd3cec3a Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Wed, 19 Jul 2017 23:04:16 -0500 Subject: [PATCH 09/82] Fixup --- src/VIDEO/vid_nv_riva128.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index 79a030d69..97ed1080f 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -1010,7 +1010,7 @@ static uint8_t riva128_pextdev_read(uint32_t addr, void *p) else ret = 0x00; break; } - case 0x04: + case 0x04: case 0x05: //Bits 12-13 of the NV4+ strap set 0 configure the GPU's PCI device ID. ret = (riva128->pextdev.boot_0 & 0x80000000) ? (0x8f | ((riva128->pextdev.boot_0 >> 8) & 0x30)) : 0x8f; break; From ca49a768b79320f6975d34607f60607a8bbbf299 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Thu, 20 Jul 2017 02:44:32 -0500 Subject: [PATCH 10/82] Fixup --- src/VIDEO/vid_nv_riva128.c | 177 ++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 90 deletions(-) diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index 97ed1080f..1bb638e50 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -253,18 +253,18 @@ const char* riva128_pfifo_interrupts[32] = "CACHE_ERROR","","","","RUNOUT","","","","RUNOUT_OVERFLOW","","","","DMA_PUSHER","","","","DMA_PTE","","","","","","","","","","","","","","","" }; -static uint32_t riva128_ramht_lookup(uint32_t handle, void *p); -//static void riva128_pgraph_volatile_reset(void *p); + uint32_t riva128_ramht_lookup(uint32_t handle, void *p); +// void riva128_pgraph_volatile_reset(void *p); -static uint8_t riva128_pci_read(int func, int addr, void *p); -static void riva128_pci_write(int func, int addr, uint8_t val, void *p); + uint8_t riva128_pci_read(int func, int addr, void *p); + void riva128_pci_write(int func, int addr, uint8_t val, void *p); -static uint8_t riva128_in(uint16_t addr, void *p); -static void riva128_out(uint16_t addr, uint8_t val, void *p); + uint8_t riva128_in(uint16_t addr, void *p); + void riva128_out(uint16_t addr, uint8_t val, void *p); -static void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p); + void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p); -/*static riva128_color_t riva128_pgraph_expand_color(uint32_t ctx, uint32_t color) +/* riva128_color_t riva128_pgraph_expand_color(uint32_t ctx, uint32_t color) { riva128_color_t ret; int format = ctx & 7; @@ -309,7 +309,7 @@ static void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p); return ret; } -static uint32_t riva128_pgraph_blend_factor(uint32_t alpha, uint32_t beta) + uint32_t riva128_pgraph_blend_factor(uint32_t alpha, uint32_t beta) { if(beta == 0xff) return alpha; if(alpha == 0xff) return beta; @@ -318,7 +318,7 @@ static uint32_t riva128_pgraph_blend_factor(uint32_t alpha, uint32_t beta) return (alpha * beta) >> 1; } -static uint32_t riva128_pgraph_do_blend(uint32_t factor, uint32_t dst, uint32_t src, int is_r5g5b5) + uint32_t riva128_pgraph_do_blend(uint32_t factor, uint32_t dst, uint32_t src, int is_r5g5b5) { factor &= 0xf8; if(factor == 0xf8) return src; @@ -333,7 +333,7 @@ static uint32_t riva128_pgraph_do_blend(uint32_t factor, uint32_t dst, uint32_t return ((dst * (0x100 - factor)) + (src * factor)) >> 6; }*/ -static uint8_t riva128_pmc_read(uint32_t addr, void *p) + uint8_t riva128_pmc_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -440,7 +440,7 @@ static uint8_t riva128_pmc_read(uint32_t addr, void *p) return ret; } -static void riva128_pmc_write(uint32_t addr, uint32_t val, void *p) + void riva128_pmc_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; //pclog("RIVA 128 PMC write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -463,7 +463,7 @@ static void riva128_pmc_write(uint32_t addr, uint32_t val, void *p) } } -static void riva128_pmc_interrupt(int num, void *p) + void riva128_pmc_interrupt(int num, void *p) { //pclog("RIVA 128 PMC interrupt #%d fired!\n", num); riva128_t *riva128 = (riva128_t *)p; @@ -476,7 +476,7 @@ static void riva128_pmc_interrupt(int num, void *p) } } -static uint8_t riva128_pbus_read(uint32_t addr, void *p) + uint8_t riva128_pbus_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -516,7 +516,7 @@ static uint8_t riva128_pbus_read(uint32_t addr, void *p) return ret; } -static void riva128_pbus_write(uint32_t addr, uint32_t val, void *p) + void riva128_pbus_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; //pclog("RIVA 128 PBUS write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -540,7 +540,7 @@ static void riva128_pbus_write(uint32_t addr, uint32_t val, void *p) } } -static uint8_t riva128_pfifo_read(uint32_t addr, void *p) + uint8_t riva128_pfifo_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -669,7 +669,7 @@ static uint8_t riva128_pfifo_read(uint32_t addr, void *p) return ret; } -static void riva128_pfifo_write(uint32_t addr, uint32_t val, void *p) + void riva128_pfifo_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; // pclog("RIVA 128 PFIFO write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -729,7 +729,7 @@ static void riva128_pfifo_write(uint32_t addr, uint32_t val, void *p) } } -static void riva128_pfifo_interrupt(int num, void *p) + void riva128_pfifo_interrupt(int num, void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -738,7 +738,7 @@ static void riva128_pfifo_interrupt(int num, void *p) riva128_pmc_interrupt(8, riva128); } -static uint8_t riva128_ptimer_read(uint32_t addr, void *p) + uint8_t riva128_ptimer_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -839,7 +839,7 @@ static uint8_t riva128_ptimer_read(uint32_t addr, void *p) return ret; } -static void riva128_ptimer_write(uint32_t addr, uint32_t val, void *p) + void riva128_ptimer_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; pclog("RIVA 128 PTIMER write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -874,7 +874,7 @@ static void riva128_ptimer_write(uint32_t addr, uint32_t val, void *p) } } -static void riva128_ptimer_interrupt(int num, void *p) + void riva128_ptimer_interrupt(int num, void *p) { //pclog("RIVA 128 PTIMER interrupt #%d fired!\n", num); riva128_t *riva128 = (riva128_t *)p; @@ -884,7 +884,7 @@ static void riva128_ptimer_interrupt(int num, void *p) riva128_pmc_interrupt(20, riva128); } -static uint8_t riva128_pfb_read(uint32_t addr, void *p) + uint8_t riva128_pfb_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -953,7 +953,7 @@ static uint8_t riva128_pfb_read(uint32_t addr, void *p) return ret; } -static void riva128_pfb_write(uint32_t addr, uint32_t val, void *p) + void riva128_pfb_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; //pclog("RIVA 128 PFB write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -979,9 +979,9 @@ static void riva128_pfb_write(uint32_t addr, uint32_t val, void *p) } } -static uint8_t riva128_pextdev_read(uint32_t addr, void *p) +uint8_t riva128_pextdev_read(uint32_t addr, void *p) { - //riva128_t *riva128 = (riva128_t *)p; + riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; //pclog("RIVA 128 PEXTDEV read %08X %04X:%08X\n", addr, CS, cpu_state.pc); @@ -1009,20 +1009,18 @@ static uint8_t riva128_pextdev_read(uint32_t addr, void *p) if(!riva128->is_nv3t) ret = 0x02; else ret = 0x00; break; - } case 0x04: case 0x05: //Bits 12-13 of the NV4+ strap set 0 configure the GPU's PCI device ID. ret = (riva128->pextdev.boot_0 & 0x80000000) ? (0x8f | ((riva128->pextdev.boot_0 >> 8) & 0x30)) : 0x8f; break; + break; } - break; - break; } return ret; } -static void riva128_pextdev_write(uint32_t addr, uint32_t val, void *p) +void riva128_pextdev_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; //pclog("RIVA 128 PEXTDEV write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -1040,7 +1038,7 @@ static void riva128_pextdev_write(uint32_t addr, uint32_t val, void *p) } } -static void rivatnt_pgraph_ctx_switch(void *p) +void rivatnt_pgraph_ctx_switch(void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -1086,7 +1084,7 @@ static void rivatnt_pgraph_ctx_switch(void *p) } } -static uint8_t riva128_pgraph_read(uint32_t addr, void *p) + uint8_t riva128_pgraph_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -1470,7 +1468,7 @@ static uint8_t riva128_pgraph_read(uint32_t addr, void *p) return ret; } -static void riva128_pgraph_write(uint32_t addr, uint32_t val, void *p) + void riva128_pgraph_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; pclog("RIVA 128 PGRAPH write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -1616,7 +1614,7 @@ static void riva128_pgraph_write(uint32_t addr, uint32_t val, void *p) } } -static void riva128_pgraph_interrupt(int num, void *p) + void riva128_pgraph_interrupt(int num, void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -1625,7 +1623,7 @@ static void riva128_pgraph_interrupt(int num, void *p) riva128_pmc_interrupt(12, riva128); } -static void riva128_pgraph_invalid_interrupt(int num, void *p) + void riva128_pgraph_invalid_interrupt(int num, void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -1634,7 +1632,7 @@ static void riva128_pgraph_invalid_interrupt(int num, void *p) riva128_pgraph_interrupt(0, riva128); } -static uint8_t riva128_pramdac_read(uint32_t addr, void *p) + uint8_t riva128_pramdac_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -1708,7 +1706,7 @@ static uint8_t riva128_pramdac_read(uint32_t addr, void *p) return ret; } -static void riva128_pramdac_write(uint32_t addr, uint32_t val, void *p) + void riva128_pramdac_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_t* svga = &riva128->svga; @@ -1746,7 +1744,7 @@ static void riva128_pramdac_write(uint32_t addr, uint32_t val, void *p) } } -static uint32_t riva128_ramht_lookup(uint32_t handle, void *p) + uint32_t riva128_ramht_lookup(uint32_t handle, void *p) { riva128_t *riva128 = (riva128_t *)p; uint32_t ramht_base = riva128->pfifo.ramht_addr; @@ -1781,7 +1779,7 @@ static uint32_t riva128_ramht_lookup(uint32_t handle, void *p) return riva128->pramin[ramht_base + (hash * 8)]; } -static void riva128_puller_exec_method(int chanid, int subchanid, int offset, uint32_t val, void *p) + void riva128_puller_exec_method(int chanid, int subchanid, int offset, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; pclog("RIVA 128 Puller executing method %04X on channel %01X[%01X] %04X:%08X\n", offset, chanid, subchanid, val, CS, cpu_state.pc); @@ -1831,7 +1829,7 @@ static void riva128_puller_exec_method(int chanid, int subchanid, int offset, ui } } -static void riva128_pusher_run(int chanid, void *p) + void riva128_pusher_run(int chanid, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_t *svga = &riva128->svga; @@ -1868,7 +1866,7 @@ static void riva128_pusher_run(int chanid, void *p) } } -static void riva128_user_write(uint32_t addr, uint32_t val, void *p) + void riva128_user_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; int chanid = (addr >> 16) & 0xf; @@ -1900,7 +1898,7 @@ static void riva128_user_write(uint32_t addr, uint32_t val, void *p) } } -static uint8_t riva128_mmio_read(uint32_t addr, void *p) + uint8_t riva128_mmio_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -1936,21 +1934,21 @@ static uint8_t riva128_mmio_read(uint32_t addr, void *p) return ret; } -static uint16_t riva128_mmio_read_w(uint32_t addr, void *p) + uint16_t riva128_mmio_read_w(uint32_t addr, void *p) { addr &= 0xffffff; //pclog("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); return (riva128_mmio_read(addr+0,p) << 0) | (riva128_mmio_read(addr+1,p) << 8); } -static uint32_t riva128_mmio_read_l(uint32_t addr, void *p) + uint32_t riva128_mmio_read_l(uint32_t addr, void *p) { addr &= 0xffffff; //pclog("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); return (riva128_mmio_read(addr+0,p) << 0) | (riva128_mmio_read(addr+1,p) << 8) | (riva128_mmio_read(addr+2,p) << 16) | (riva128_mmio_read(addr+3,p) << 24); } -static void riva128_mmio_write(uint32_t addr, uint8_t val, void *p) + void riva128_mmio_write(uint32_t addr, uint8_t val, void *p) { addr &= 0xffffff; //pclog("RIVA 128 MMIO write %08X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); @@ -1967,7 +1965,7 @@ static void riva128_mmio_write(uint32_t addr, uint8_t val, void *p) } } -static void riva128_mmio_write_w(uint32_t addr, uint16_t val, void *p) + void riva128_mmio_write_w(uint32_t addr, uint16_t val, void *p) { uint32_t tmp; addr &= 0xffffff; @@ -1978,7 +1976,7 @@ static void riva128_mmio_write_w(uint32_t addr, uint16_t val, void *p) riva128_mmio_write_l(addr, tmp, p); } -static void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p) + void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -2013,7 +2011,7 @@ static void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p) } } -static void riva128_ptimer_tick(void *p) + void riva128_ptimer_tick(void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -2035,7 +2033,7 @@ static void riva128_ptimer_tick(void *p) } } -static void riva128_mclk_poll(void *p) + void riva128_mclk_poll(void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -2044,7 +2042,7 @@ static void riva128_mclk_poll(void *p) riva128->mtime += cpuclock / riva128->mfreq; } -static void riva128_nvclk_poll(void *p) + void riva128_nvclk_poll(void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -2053,14 +2051,14 @@ static void riva128_nvclk_poll(void *p) riva128->nvtime += cpuclock / riva128->nvfreq; } -static void riva128_vblank_poll(svga_t *svga) + void riva128_vblank_poll(svga_t *svga) { riva128_t *riva128 = (riva128_t *)svga->p; riva128_pmc_interrupt(24, riva128); } -static uint8_t riva128_rma_in(uint16_t addr, void *p) + uint8_t riva128_rma_in(uint16_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -2094,7 +2092,7 @@ static uint8_t riva128_rma_in(uint16_t addr, void *p) return ret; } -static void riva128_rma_out(uint16_t addr, uint8_t val, void *p) + void riva128_rma_out(uint16_t addr, uint8_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_t* svga = &riva128->svga; @@ -2156,7 +2154,7 @@ static void riva128_rma_out(uint16_t addr, uint8_t val, void *p) if(addr & 0x10) riva128->rma.addr+=4; } -static uint8_t riva128_in(uint16_t addr, void *p) + uint8_t riva128_in(uint16_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_t* svga = &riva128->svga; @@ -2219,7 +2217,7 @@ static uint8_t riva128_in(uint16_t addr, void *p) return ret; } -static void riva128_out(uint16_t addr, uint8_t val, void *p) + void riva128_out(uint16_t addr, uint8_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_t *svga = &riva128->svga; @@ -2335,14 +2333,14 @@ static void riva128_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); } -static uint32_t riva128_ramin_readl(uint32_t addr, void *p) + uint32_t riva128_ramin_readl(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint32_t ret = riva128->pramin[(addr & 0x1ffffc) >> 2]; return ret; } -static uint8_t riva128_ramin_readb(uint32_t addr, void *p) + uint8_t riva128_ramin_readb(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint32_t ret = riva128->pramin[(addr & 0x1ffffc) >> 2]; @@ -2350,7 +2348,7 @@ static uint8_t riva128_ramin_readb(uint32_t addr, void *p) return ret; } -static uint16_t riva128_ramin_readw(uint32_t addr, void *p) + uint16_t riva128_ramin_readw(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint32_t ret = riva128->pramin[(addr & 0x1ffffc) >> 2]; @@ -2358,13 +2356,13 @@ static uint16_t riva128_ramin_readw(uint32_t addr, void *p) return ret; } -static void riva128_ramin_writel(uint32_t addr, uint32_t val, void *p) + void riva128_ramin_writel(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; riva128->pramin[(addr & 0x1ffffc) >> 2] = val; } -static void riva128_ramin_writeb(uint32_t addr, uint8_t val, void *p) + void riva128_ramin_writeb(uint32_t addr, uint8_t val, void *p) { uint32_t tmp = riva128_ramin_readl(addr,p); tmp &= ~(0xff << ((addr & 3) << 3)); @@ -2372,7 +2370,7 @@ static void riva128_ramin_writeb(uint32_t addr, uint8_t val, void *p) riva128_ramin_writel(addr, tmp, p); } -static void riva128_ramin_writew(uint32_t addr, uint16_t val, void *p) + void riva128_ramin_writew(uint32_t addr, uint16_t val, void *p) { uint32_t tmp = riva128_ramin_readl(addr,p); tmp &= ~(0xffff << ((addr & 2) << 4)); @@ -2380,7 +2378,7 @@ static void riva128_ramin_writew(uint32_t addr, uint16_t val, void *p) riva128_ramin_writel(addr, tmp, p); } -static uint8_t riva128_pci_read(int func, int addr, void *p) + uint8_t riva128_pci_read(int func, int addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; @@ -2478,7 +2476,7 @@ static uint8_t riva128_pci_read(int func, int addr, void *p) return ret; } -static void riva128_reenable_svga_mappings(svga_t *svga) + void riva128_reenable_svga_mappings(svga_t *svga) { switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ { @@ -2501,7 +2499,7 @@ static void riva128_reenable_svga_mappings(svga_t *svga) } } -static void riva128_pci_write(int func, int addr, uint8_t val, void *p) + void riva128_pci_write(int func, int addr, uint8_t val, void *p) { //pclog("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); riva128_t *riva128 = (riva128_t *)p; @@ -2616,7 +2614,7 @@ static void riva128_pci_write(int func, int addr, uint8_t val, void *p) } } -static void rivatnt_pci_write(int func, int addr, uint8_t val, void *p) + void rivatnt_pci_write(int func, int addr, uint8_t val, void *p) { //pclog("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); riva128_t *riva128 = (riva128_t *)p; @@ -2727,7 +2725,7 @@ static void rivatnt_pci_write(int func, int addr, uint8_t val, void *p) } } -static void riva128_recalctimings(svga_t *svga) + void riva128_recalctimings(svga_t *svga) { riva128_t *riva128 = (riva128_t *)svga->p; @@ -2807,7 +2805,7 @@ static void riva128_recalctimings(svga_t *svga) riva128->nvfreq = freq; } -static void *riva128_init() + void *riva128_init() { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -2936,7 +2934,7 @@ static void *riva128_init() return riva128; } -static void riva128_close(void *p) + void riva128_close(void *p) { riva128_t *riva128 = (riva128_t *)p; FILE *f = fopen("vram.dmp", "wb"); @@ -2948,33 +2946,33 @@ static void riva128_close(void *p) free(riva128); } -static int riva128_available() + int riva128_available() { return rom_present(L"roms/video/nv_riva128/Diamond_V330_rev-e.vbi"); } -static void riva128_speed_changed(void *p) + void riva128_speed_changed(void *p) { riva128_t *riva128 = (riva128_t *)p; svga_recalctimings(&riva128->svga); } -static void riva128_force_redraw(void *p) +void riva128_force_redraw(void *p) { riva128_t *riva128 = (riva128_t *)p; riva128->svga.fullchange = changeframecount; } -static void riva128_add_status_info(char *s, int max_len, void *p) +void riva128_add_status_info(char *s, int max_len, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_add_status_info(s, max_len, &riva128->svga); } -static device_config_t riva128_config[] = +device_config_t riva128_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, @@ -2994,11 +2992,11 @@ static device_config_t riva128_config[] = }, }, { - -1 + "", "", -1 } }; -/*static device_config_t riva128zx_config[] = +/* device_config_t riva128zx_config[] = { { .name = "memory", @@ -3046,7 +3044,7 @@ device_t riva128_device = riva128_config }; -static void *rivatnt_init() + void *rivatnt_init() { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -3159,7 +3157,7 @@ static void *rivatnt_init() return riva128; } -static void rivatnt_close(void *p) + void rivatnt_close(void *p) { riva128_t *riva128 = (riva128_t *)p; FILE *f = fopen("vram.dmp", "wb"); @@ -3171,33 +3169,33 @@ static void rivatnt_close(void *p) free(riva128); } -static int rivatnt_available() + int rivatnt_available() { return rom_present(L"roms/video/nv_riva128/NV4_diamond_revB.rom"); } -static void rivatnt_speed_changed(void *p) + void rivatnt_speed_changed(void *p) { riva128_t *riva128 = (riva128_t *)p; svga_recalctimings(&riva128->svga); } -static void rivatnt_force_redraw(void *p) + void rivatnt_force_redraw(void *p) { riva128_t *riva128 = (riva128_t *)p; riva128->svga.fullchange = changeframecount; } -static void rivatnt_add_status_info(char *s, int max_len, void *p) + void rivatnt_add_status_info(char *s, int max_len, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_add_status_info(s, max_len, &riva128->svga); } -static device_config_t rivatnt_config[] = + device_config_t rivatnt_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 16, @@ -3217,7 +3215,7 @@ static device_config_t rivatnt_config[] = }, }, { - -1 + "", "", -1 } }; @@ -3234,7 +3232,7 @@ device_t rivatnt_device = rivatnt_config }; -static void *rivatnt2_init() + void *rivatnt2_init() { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -3360,7 +3358,7 @@ static void *rivatnt2_init() return riva128; } -static void rivatnt2_close(void *p) + void rivatnt2_close(void *p) { riva128_t *riva128 = (riva128_t *)p; FILE *f = fopen("vram.dmp", "wb"); @@ -3372,33 +3370,33 @@ static void rivatnt2_close(void *p) free(riva128); } -static int rivatnt2_available() + int rivatnt2_available() { return rom_present(L"roms/video/nv_riva128/NV5diamond.bin") || rom_present(L"roms/video/nv_riva128/inno3d64bit.BIN") || rom_present(L"roms/video/nv_riva128/creative.BIN"); } -static void rivatnt2_speed_changed(void *p) + void rivatnt2_speed_changed(void *p) { riva128_t *riva128 = (riva128_t *)p; svga_recalctimings(&riva128->svga); } -static void rivatnt2_force_redraw(void *p) + void rivatnt2_force_redraw(void *p) { riva128_t *riva128 = (riva128_t *)p; riva128->svga.fullchange = changeframecount; } -static void rivatnt2_add_status_info(char *s, int max_len, void *p) + void rivatnt2_add_status_info(char *s, int max_len, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_add_status_info(s, max_len, &riva128->svga); } -static device_config_t rivatnt2_config[] = + device_config_t rivatnt2_config[] = { { "model", "Card model", CONFIG_SELECTION, "", 0, @@ -3451,4 +3449,3 @@ device_t rivatnt2_device = rivatnt2_add_status_info, rivatnt2_config }; - From 753937741e2542b2fd7289c8298a5fce62b3875f Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Jul 2017 14:14:43 +0200 Subject: [PATCH 11/82] Added the AWARD 386SX, 386DX, and 486 clones, all using the same BIOS (supports all of these configurations) and the OPTi 495 chipset. --- src/ibm.h | 14 ++++++++++---- src/mem.c | 9 +++++++++ src/model.c | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/ibm.h b/src/ibm.h index 3b2720941..b4fac859b 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -428,10 +428,12 @@ enum ROM_REVENGE, ROM_IBMPS1_2011, ROM_DESKPRO_386, - ROM_PORTABLE, - ROM_PORTABLEII, - ROM_PORTABLEIII, - ROM_PORTABLEIII386, /* The original Compaq Portable III shipped with an Intel 80286 CPU, but later switched to a 386DX. */ + ROM_PORTABLE, +#if 0 + ROM_PORTABLEII, + ROM_PORTABLEIII, + ROM_PORTABLEIII386, /* The original Compaq Portable III shipped with an Intel 80286 CPU, but later switched to a 386DX. */ +#endif ROM_IBMPS1_2121, ROM_AMI386DX_OPTI495, @@ -469,6 +471,10 @@ enum ROM_SPC4200P, /*Samsung SPC-4200P / SCAT / Phoenix BIOS*/ ROM_SUPER286TR, /*Hyundai Super-286TR / SCAT / Award BIOS*/ + ROM_AWARD386SX_OPTI495, + ROM_AWARD386DX_OPTI495, + ROM_AWARD486_OPTI495, + ROM_MEGAPCDX, /*386DX mdoel of the Mega PC - Note by Tohka: The documentation (that I have in German) clearly says such a model exists.*/ ROM_ZAPPA, /*Intel Advanced/ZP / 430FX / AMI BIOS / National Semiconductors PC87306*/ diff --git a/src/mem.c b/src/mem.c index b8577d06a..5ab4e5899 100644 --- a/src/mem.c +++ b/src/mem.c @@ -348,6 +348,15 @@ int loadbios() fclose(f); return 1; + case ROM_AWARD386SX_OPTI495: /*This uses the OPTi 82C495 chipset*/ + case ROM_AWARD386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ + case ROM_AWARD486_OPTI495: /*This uses the OPTi 82C495 chipset*/ + f=romfopen(L"roms/machines/award495/OPT495S.AWA",L"rb"); + if (!f) break; + fread(rom,65536,1,f); + fclose(f); + return 1; + case ROM_AMI286: f=romfopen(L"roms/machines/ami286/amic206.bin",L"rb"); if (!f) break; diff --git a/src/model.c b/src/model.c index 1b090cd42..1c2d15336 100644 --- a/src/model.c +++ b/src/model.c @@ -179,6 +179,7 @@ MODEL models[] = {"[386SX] AMI 386SX clone", ROM_AMI386SX, "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 512,16384, 128, 127, at_headland_init, NULL }, {"[386SX] Amstrad MegaPC", ROM_MEGAPC, "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE, 1, 16, 1, 127, at_wd76c10_init, NULL }, + {"[386SX] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_opti495_init, NULL }, {"[386SX] DTK 386SX clone", ROM_DTK386, "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 512,16384, 128, 127, at_neat_init, NULL }, {"[386SX] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE, 1, 16, 1, 127, ps1_m2121_init, NULL }, {"[386SX] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE, 1, 16, 1, 127, ps1_m2121_init, NULL }, @@ -186,6 +187,7 @@ MODEL models[] = {"[386DX] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_opti495_init, NULL }, {"[386DX] Amstrad MegaPC 386DX",ROM_MEGAPCDX, "megapcdx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE, 1, 16, 1, 127, at_wd76c10_init, NULL }, + {"[386DX] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_opti495_init, NULL }, {"[386DX] Compaq Deskpro 386", ROM_DESKPRO_386, "dekspro386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT, 1, 15, 1, 63, deskpro386_init, NULL }, #if 0 {"[386DX] Compaq Portable III 386",ROM_PORTABLEIII386, "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MODEL_AT, 1, 15, 1, 63, at_init, NULL }, @@ -195,6 +197,7 @@ MODEL models[] = {"[486] AMI 486 clone", ROM_AMI486, "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_ali1429_init, NULL }, {"[486] AMI WinBIOS 486", ROM_WIN486, "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_ali1429_init, NULL }, + {"[486] Award 486 clone", ROM_AWARD486_OPTI495, "award486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_opti495_init, NULL }, {"[486] DTK PKM-0038S E-2", ROM_DTK486, "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_dtk486_init, NULL }, {"[486] IBM PS/1 model 2133", ROM_IBMPS1_2133, "ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE, 1, 64, 1, 127, ps1_m2133_init, NULL }, {"[486] Rise Computer R418", ROM_R418, "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MODEL_AT | MODEL_HAS_IDE | MODEL_PCI, 1, 64, 1, 127, at_r418_init, NULL }, From 9aa45f9e2560979102cfe489748b3f51b2392528 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Jul 2017 14:35:44 +0200 Subject: [PATCH 12/82] The "Acer M3a" I/O registers are in fact SMC FDC37C932FR General Purpose I/O registers, and are now implemented as such. --- src/Makefile.mingw | 2 +- src/acerm3a.c | 38 -------------------------------------- src/fdc37c932fr.c | 5 +++++ src/model.c | 7 ------- 4 files changed, 6 insertions(+), 46 deletions(-) delete mode 100644 src/acerm3a.c diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 2b4536436..79645cb4c 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -159,7 +159,7 @@ SYSOBJ = model.o \ scat.o \ sis496.o \ wd76c10.o \ - acer386sx.o acerm3a.o amstrad.o \ + acer386sx.o amstrad.o \ compaq.o laserxt.o jim.o \ olivetti_m24.o ps1.o ps2.o ps2_mca.o \ tandy_eeprom.o tandy_rom.o diff --git a/src/acerm3a.c b/src/acerm3a.c deleted file mode 100644 index a348d2b05..000000000 --- a/src/acerm3a.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include "ibm.h" -#include "cpu/cpu.h" -#include "io.h" -#include "device.h" -#include "model.h" - - -static int acerm3a_index; - - -static void acerm3a_write(uint16_t port, uint8_t val, void *p) -{ - if (port == 0xea) - acerm3a_index = val; -} - - -static uint8_t acerm3a_read(uint16_t port, void *p) -{ - if (port == 0xeb) - { - switch (acerm3a_index) - { - case 2: - return 0xfd; - } - } - return 0xff; -} - - -void acerm3a_io_init(void) -{ - io_sethandler(0x00ea, 0x0002, acerm3a_read, NULL, NULL, acerm3a_write, NULL, NULL, NULL); -} diff --git a/src/fdc37c932fr.c b/src/fdc37c932fr.c index d5faf988e..6b9f8aa05 100644 --- a/src/fdc37c932fr.c +++ b/src/fdc37c932fr.c @@ -488,6 +488,9 @@ void fdc37c932fr_reset(void) fdc_update_drvrate(3, 0); fdc_update_max_track(79); + memset(fdc37c932fr_gpio_regs, 0, sizeof(fdc37c932fr_gpio_regs)); + fdc37c932fr_gpio_regs[2] = 0xfd; + fdc37c932fr_locked = 0; } @@ -498,6 +501,8 @@ void fdc37c932fr_init() fdc37c932fr_reset(); io_sethandler(0xe0, 0x0006, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL); + io_sethandler(0xe2, 0x0006, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL); + io_sethandler(0xe4, 0x0006, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL); io_sethandler(0xea, 0x0002, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL); io_sethandler(0x3f0, 0x0002, fdc37c932fr_read, NULL, NULL, fdc37c932fr_write, NULL, NULL, NULL); diff --git a/src/model.c b/src/model.c index 1c2d15336..204f2de88 100644 --- a/src/model.c +++ b/src/model.c @@ -779,7 +779,6 @@ void at_ap53_init(void) i430hx_init(); piix_init(7, 0x11, 0x12, 0x13, 0x14); fdc37c669_init(); - acerm3a_io_init(); device_add(&intel_flash_bxt_device); } @@ -796,14 +795,12 @@ void at_p55t2s_init(void) i430hx_init(); piix_init(7, 0x12, 0x11, 0x14, 0x13); pc87306_init(); - acerm3a_io_init(); device_add(&intel_flash_bxt_device); } void at_acerm3a_init(void) { at_ide_init(); - memregs_init(); powermate_memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_slot(0xc); @@ -813,14 +810,12 @@ void at_acerm3a_init(void) i430hx_init(); piix3_init(7, 0xc, 0xd, 0xe, 0xf); fdc37c932fr_init(); - acerm3a_io_init(); device_add(&intel_flash_bxb_device); } void at_acerv35n_init(void) { at_ide_init(); - memregs_init(); powermate_memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_slot(0x11); @@ -830,7 +825,6 @@ void at_acerv35n_init(void) i430hx_init(); piix3_init(7, 0x11, 0x12, 0x13, 0x14); fdc37c932fr_init(); - acerm3a_io_init(); device_add(&intel_flash_bxb_device); } @@ -884,7 +878,6 @@ void at_p55tvp4_init(void) void at_p55va_init(void) { at_ide_init(); - memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_slot(8); pci_slot(9); From fa0f77735c60d990e4ab2cd34c20732363b5e177 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Jul 2017 15:22:21 +0200 Subject: [PATCH 13/82] Attempt to fix the Settings bugs. --- src/WIN/win_settings.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/WIN/win_settings.c b/src/WIN/win_settings.c index 6000827be..eb2866f7c 100644 --- a/src/WIN/win_settings.c +++ b/src/WIN/win_settings.c @@ -663,7 +663,7 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w h = GetDlgItem(hdlg, IDC_MEMTEXT); SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, sizeof(stransi)); + wcstombs(stransi, lptsTemp, 512); sscanf(stransi, "%i", &temp_mem_size); temp_mem_size &= ~(models[temp_model].ram_granularity - 1); if (temp_mem_size < models[temp_model].min_ram) @@ -765,7 +765,7 @@ static BOOL CALLBACK win_settings_video_proc(HWND hdlg, UINT message, WPARAM wPa h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, sizeof(stransi)); + wcstombs(stransi, lptsTemp, 512); gfx = video_card_getid(stransi); h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); @@ -792,7 +792,7 @@ static BOOL CALLBACK win_settings_video_proc(HWND hdlg, UINT message, WPARAM wPa h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, sizeof(stransi)); + wcstombs(stransi, lptsTemp, 512); gfx = video_card_getid(stransi); temp_gfxcard = video_new_to_old(gfx); @@ -828,7 +828,7 @@ static BOOL CALLBACK win_settings_video_proc(HWND hdlg, UINT message, WPARAM wPa h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, sizeof(stransi)); + wcstombs(stransi, lptsTemp, 512); deviceconfig_open(hdlg, (void *)video_card_getdevice(video_card_getid(stransi))); free(stransi); @@ -843,7 +843,7 @@ static BOOL CALLBACK win_settings_video_proc(HWND hdlg, UINT message, WPARAM wPa h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, sizeof(stransi)); + wcstombs(stransi, lptsTemp, 512); temp_gfxcard = video_new_to_old(video_card_getid(stransi)); h = GetDlgItem(hdlg, IDC_COMBO_VIDEO_SPEED); @@ -2436,7 +2436,7 @@ static void get_edit_box_contents(HWND hdlg, int id, uint64_t *val) h = GetDlgItem(hdlg, id); SendMessage(h, WM_GETTEXT, 255, (LPARAM) szText); - wcstombs(stransi, szText, sizeof(stransi)); + wcstombs(stransi, szText, 256); sscanf(stransi, "%" PRIu64, val); } From 76222651ba8293f663c02272807dc8d178c9b436 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Jul 2017 20:55:12 +0200 Subject: [PATCH 14/82] EGA now renders at the correct size. --- src/VIDEO/vid_ega.c | 17 +++++++++++++---- src/VIDEO/vid_svga.c | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/VIDEO/vid_ega.c b/src/VIDEO/vid_ega.c index 0920e3884..a3c779ebb 100644 --- a/src/VIDEO/vid_ega.c +++ b/src/VIDEO/vid_ega.c @@ -454,7 +454,7 @@ void ega_recalctimings(ega_t *ega) if (ega->crtc[7] & 1) ega->vtotal |= 0x100; if (ega->crtc[7] & 32) ega->vtotal |= 0x200; - ega->vtotal++; + ega->vtotal += 2; if (ega->crtc[7] & 2) ega->dispend |= 0x100; if (ega->crtc[7] & 64) ega->dispend |= 0x200; @@ -466,7 +466,7 @@ void ega_recalctimings(ega_t *ega) if (ega->crtc[7] & 0x10) ega->split |= 0x100; if (ega->crtc[9] & 0x40) ega->split |= 0x200; - ega->split+=2; + ega->split++; ega->hdisp = ega->crtc[1]; ega->hdisp++; @@ -572,6 +572,8 @@ void ega_poll(void *p) } ega->displine++; + if (ega->interlace) + ega->displine++; if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) ega->stat &= ~8; ega->vslines++; @@ -595,6 +597,8 @@ void ega_poll(void *p) ega->con = 0; ega->maback += (ega->rowoffset << 3); + if (ega->interlace) + ega->maback += (ega->rowoffset << 3); ega->maback &= ega->vrammask; ega->ma = ega->maback; } @@ -631,10 +635,14 @@ void ega_poll(void *p) ega->stat |= 8; if (ega->seqregs[1] & 8) x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9) * 2; else x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9); + + if (ega->interlace && !ega->oddeven) ega->lastline++; + if (ega->interlace && ega->oddeven) ega->firstline--; + if ((x != xsize || (ega->lastline - ega->firstline) != ysize) || update_overscan) { xsize = x; - ysize = ega->lastline - ega->firstline; + ysize = ega->lastline - ega->firstline + 1; if (xsize < 64) xsize = 640; if (ysize < 32) ysize = 200; y_add = enable_overscan ? 14 : 0; @@ -714,7 +722,7 @@ void ega_poll(void *p) } } - video_blit_memtoscreen(32, 0, ega->firstline, ega->lastline + y_add_ex, xsize + x_add_ex, ega->lastline - ega->firstline + y_add_ex); + video_blit_memtoscreen(32, 0, ega->firstline, ega->lastline + 1 + y_add_ex, xsize + x_add_ex, ega->lastline - ega->firstline + 1 + y_add_ex); frames++; @@ -754,6 +762,7 @@ void ega_poll(void *p) ega->vc = 0; ega->sc = 0; ega->dispon = 1; + ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; ega->displine = 0; ega->scrollcache = ega->attrregs[0x13] & 7; } diff --git a/src/VIDEO/vid_svga.c b/src/VIDEO/vid_svga.c index 3690bc2ac..01542b93b 100644 --- a/src/VIDEO/vid_svga.c +++ b/src/VIDEO/vid_svga.c @@ -1610,7 +1610,7 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) return; } - if ((wx!=xsize || wy!=ysize) && !vid_resize) + if (((wx!=xsize) || ((wy + 1)!=ysize)) && !vid_resize) { xsize=wx; ysize=wy+1; From 807631ca01b21640cb9136fe527ec5f40099da9a Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Jul 2017 21:05:27 +0200 Subject: [PATCH 15/82] Reworked the force 4:3 code a bit to reduce rounding errors. --- src/WIN/win.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/WIN/win.c b/src/WIN/win.c index dc30da3fd..38649ac7a 100644 --- a/src/WIN/win.c +++ b/src/WIN/win.c @@ -165,6 +165,8 @@ void updatewindowsize(int x, int y) int temp_overscan_x = overscan_x; int temp_overscan_y = overscan_y; + double dx, dy, dtx, dty; + if (vid_resize) return; if (x < 160) x = 160; @@ -182,30 +184,37 @@ void updatewindowsize(int x, int y) if (force_43) { + dx = (double) x; + dtx = (double) temp_overscan_x; + + dy = (double) y; + dty = (double) temp_overscan_y; + /* Account for possible overscan. */ if (temp_overscan_y == 16) { /* CGA */ - unscaled_size_y = ((int) (((double) (x - temp_overscan_x) / 4.0) * 3.0)) + temp_overscan_y; + dy = (((dx - dtx) / 4.0) * 3.0) + dty; } else if (temp_overscan_y < 16) { /* MDA/Hercules */ - unscaled_size_y = ((int) (((double) (x) / 4.0) * 3.0)); + dy = (x / 4.0) * 3.0; } else { if (enable_overscan) { /* EGA/(S)VGA with overscan */ - unscaled_size_y = ((int) (((double) (x - temp_overscan_x) / 4.0) * 3.0)) + temp_overscan_y; + dy = (((dx - dtx) / 4.0) * 3.0) + dty; } else { /* EGA/(S)VGA without overscan */ - unscaled_size_y = ((int) (((double) (x) / 4.0) * 3.0)); + dy = (x / 4.0) * 3.0; } } + unscaled_size_y = (int) dy; } else { From 705ba08d8b7d9e30e6e4e86522552c85a39f10d8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Jul 2017 22:15:13 +0200 Subject: [PATCH 16/82] The AOpen AP53 and the ASUS P/I-P55T2S now correctly use the PIIX3 rather than the PIIX. --- src/model.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/model.c b/src/model.c index 204f2de88..4e6887441 100644 --- a/src/model.c +++ b/src/model.c @@ -777,7 +777,7 @@ void at_ap53_init(void) pci_slot(0x13); pci_slot(0x14); i430hx_init(); - piix_init(7, 0x11, 0x12, 0x13, 0x14); + piix3_init(7, 0x11, 0x12, 0x13, 0x14); fdc37c669_init(); device_add(&intel_flash_bxt_device); } @@ -793,7 +793,7 @@ void at_p55t2s_init(void) pci_slot(0x14); pci_slot(0x13); i430hx_init(); - piix_init(7, 0x12, 0x11, 0x14, 0x13); + piix3_init(7, 0x12, 0x11, 0x14, 0x13); pc87306_init(); device_add(&intel_flash_bxt_device); } From 6cab132b307680be9352248ee53693c98b75e5d2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Jul 2017 00:14:17 +0200 Subject: [PATCH 17/82] Updated the copyright header of vid_ega.c. --- src/VIDEO/vid_ega.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VIDEO/vid_ega.c b/src/VIDEO/vid_ega.c index a3c779ebb..10148ad55 100644 --- a/src/VIDEO/vid_ega.c +++ b/src/VIDEO/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.c 1.0.2 2017/06/05 + * Version: @(#)vid_ega.c 1.0.3 2017/07/21 * * Author: Sarah Walker, * Miran Grca, From dd93543badaf464e606521e23aea5fed5f697f99 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Jul 2017 10:51:54 +0200 Subject: [PATCH 18/82] Applied the mainline PCem commit that reorganizes the REP instructions. --- src/CPU/386_dynarec.c | 822 --------------------------------------- src/CPU/386_ops.h | 182 +++++++++ src/CPU/codegen_ops.c | 94 +++++ src/CPU/codegen_ops.h | 2 + src/CPU/codegen_x86-64.c | 16 + src/CPU/codegen_x86.c | 15 + src/CPU/cpu.c | 8 + src/CPU/x86_ops.h | 10 + src/CPU/x86_ops_prefix.h | 97 ++++- src/CPU/x86_ops_rep.h | 629 +++++++++++++++++++++++++++++- src/ibm.h | 1 - 11 files changed, 1036 insertions(+), 840 deletions(-) diff --git a/src/CPU/386_dynarec.c b/src/CPU/386_dynarec.c index a2a36cfa1..d6c915d58 100644 --- a/src/CPU/386_dynarec.c +++ b/src/CPU/386_dynarec.c @@ -401,828 +401,6 @@ int checkio(int port) return d&(1<<(port&7)); } -int rep386(int fv) -{ - uint8_t temp; - uint32_t c; - uint8_t temp2; - uint16_t tempw,tempw2,of; - uint32_t ipc = cpu_state.oldpc; - uint32_t rep32 = cpu_state.op32; - uint32_t templ,templ2; - int tempz; - int tempi; - /*Limit the amount of time the instruction is uninterruptable for, so - that high frequency timers still work okay. This amount is different - for interpreter and recompiler*/ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); - int reads = 0, reads_l = 0, writes = 0, writes_l = 0, total_cycles = 0; - - if (trap) - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ - - cpu_reps++; - - flags_rebuild(); - of = flags; - startrep: - temp=opcode2=readmemb(cs,cpu_state.pc); cpu_state.pc++; - c=(rep32&0x200)?ECX:CX; - switch (temp|rep32) - { - case 0xC3: case 0x1C3: case 0x2C3: case 0x3C3: - cpu_state.pc--; - break; - case 0x08: - cpu_state.pc=ipc+1; - break; - case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/ - cpu_state.ea_seg = &_es; - PREFETCH_PREFIX(); - goto startrep; - break; - case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/ - cpu_state.ea_seg = &_cs; - PREFETCH_PREFIX(); - goto startrep; - case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/ - cpu_state.ea_seg = &_ss; - PREFETCH_PREFIX(); - goto startrep; - case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/ - cpu_state.ea_seg = &_ds; - PREFETCH_PREFIX(); - goto startrep; - case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/ - cpu_state.ea_seg = &_fs; - PREFETCH_PREFIX(); - goto startrep; - case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/ - cpu_state.ea_seg = &_gs; - PREFETCH_PREFIX(); - goto startrep; - case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/ - rep32 = (rep32 & 0x200) | ((use32 ^ 0x100) & 0x100); - PREFETCH_PREFIX(); - goto startrep; - case 0x67: case 0x167: case 0x267: case 0x367: /*Address size prefix*/ - rep32 = (rep32 & 0x100) | ((use32 ^ 0x200) & 0x200); - PREFETCH_PREFIX(); - goto startrep; - case 0x6C: case 0x16C: /*REP INSB*/ - if (c>0) - { - checkio_perm(DX); - temp2=inb(DX); - writememb(es,DI,temp2); - if (cpu_state.abrt) break; - if (flags&D_FLAG) DI--; - else DI++; - c--; - cycles-=15; - reads++; writes++; total_cycles += 15; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x26C: case 0x36C: /*REP INSB*/ - if (c>0) - { - checkio_perm(DX); - temp2=inb(DX); - writememb(es,EDI,temp2); - if (cpu_state.abrt) break; - if (flags&D_FLAG) EDI--; - else EDI++; - c--; - cycles-=15; - reads++; writes++; total_cycles += 15; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x6D: /*REP INSW*/ - if (c>0) - { - tempw=inw(DX); - writememw(es,DI,tempw); - if (cpu_state.abrt) break; - if (flags&D_FLAG) DI-=2; - else DI+=2; - c--; - cycles-=15; - reads++; writes++; total_cycles += 15; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x16D: /*REP INSL*/ - if (c>0) - { - templ=inl(DX); - writememl(es,DI,templ); - if (cpu_state.abrt) break; - if (flags&D_FLAG) DI-=4; - else DI+=4; - c--; - cycles-=15; - reads_l++; writes_l++; total_cycles += 15; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x26D: /*REP INSW*/ - if (c>0) - { - tempw=inw(DX); - writememw(es,EDI,tempw); - if (cpu_state.abrt) break; - if (flags&D_FLAG) EDI-=2; - else EDI+=2; - c--; - cycles-=15; - reads++; writes++; total_cycles += 15; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x36D: /*REP INSL*/ - if (c>0) - { - templ=inl(DX); - writememl(es,EDI,templ); - if (cpu_state.abrt) break; - if (flags&D_FLAG) EDI-=4; - else EDI+=4; - c--; - cycles-=15; - reads_l++; writes_l++; total_cycles += 15; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x6E: case 0x16E: /*REP OUTSB*/ - if (c>0) - { - temp2 = readmemb(cpu_state.ea_seg->base, SI); - if (cpu_state.abrt) break; - checkio_perm(DX); - outb(DX,temp2); - if (flags&D_FLAG) SI--; - else SI++; - c--; - cycles-=14; - reads++; writes++; total_cycles += 14; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x26E: case 0x36E: /*REP OUTSB*/ - if (c>0) - { - temp2 = readmemb(cpu_state.ea_seg->base, ESI); - if (cpu_state.abrt) break; - checkio_perm(DX); - outb(DX,temp2); - if (flags&D_FLAG) ESI--; - else ESI++; - c--; - cycles-=14; - reads++; writes++; total_cycles += 14; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x6F: /*REP OUTSW*/ - if (c>0) - { - tempw = readmemw(cpu_state.ea_seg->base, SI); - if (cpu_state.abrt) break; - outw(DX,tempw); - if (flags&D_FLAG) SI-=2; - else SI+=2; - c--; - cycles-=14; - reads++; writes++; total_cycles += 14; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x16F: /*REP OUTSL*/ - if (c > 0) - { - templ = readmeml(cpu_state.ea_seg->base, SI); - if (cpu_state.abrt) break; - outl(DX, templ); - if (flags & D_FLAG) SI -= 4; - else SI += 4; - c--; - cycles -= 14; - reads_l++; writes_l++; total_cycles += 14; - } - if (c > 0) { firstrepcycle = 0; cpu_state.pc = ipc; } - else firstrepcycle = 1; - break; - case 0x26F: /*REP OUTSW*/ - if (c>0) - { - tempw = readmemw(cpu_state.ea_seg->base, ESI); - if (cpu_state.abrt) break; - outw(DX,tempw); - if (flags&D_FLAG) ESI-=2; - else ESI+=2; - c--; - cycles-=14; - reads++; writes++; total_cycles += 14; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x36F: /*REP OUTSL*/ - if (c > 0) - { - templ = readmeml(cpu_state.ea_seg->base, ESI); - if (cpu_state.abrt) break; - outl(DX, templ); - if (flags & D_FLAG) ESI -= 4; - else ESI += 4; - c--; - cycles -= 14; - reads_l++; writes_l++; total_cycles += 14; - } - if (c > 0) { firstrepcycle = 0; cpu_state.pc = ipc; } - else firstrepcycle = 1; - break; - case 0x90: case 0x190: /*REP NOP*/ - case 0x290: case 0x390: - break; - case 0xA4: case 0x1A4: /*REP MOVSB*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, DI, DI); - temp2 = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) break; - writememb(es,DI,temp2); if (cpu_state.abrt) break; - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - c--; - cycles-=(is486)?3:4; - ins++; - reads++; writes++; total_cycles += is486 ? 3 : 4; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x2A4: case 0x3A4: /*REP MOVSB*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, EDI, EDI); - temp2 = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) break; - writememb(es,EDI,temp2); if (cpu_state.abrt) break; - if (flags&D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } - c--; - cycles-=(is486)?3:4; - ins++; - reads++; writes++; total_cycles += is486 ? 3 : 4; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0xA5: /*REP MOVSW*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, DI, DI+1); - tempw = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) break; - writememw(es,DI,tempw); if (cpu_state.abrt) break; - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - c--; - cycles-=(is486)?3:4; - ins++; - reads++; writes++; total_cycles += is486 ? 3 : 4; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x1A5: /*REP MOVSL*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, DI, DI+3); - templ = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) break; - writememl(es,DI,templ); if (cpu_state.abrt) break; - if (flags&D_FLAG) { DI-=4; SI-=4; } - else { DI+=4; SI+=4; } - c--; - cycles-=(is486)?3:4; - ins++; - reads_l++; writes_l++; total_cycles += is486 ? 3 : 4; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x2A5: /*REP MOVSW*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, EDI, EDI+1); - tempw = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) break; - writememw(es,EDI,tempw); if (cpu_state.abrt) break; - if (flags&D_FLAG) { EDI-=2; ESI-=2; } - else { EDI+=2; ESI+=2; } - c--; - cycles-=(is486)?3:4; - ins++; - reads++; writes++; total_cycles += is486 ? 3 : 4; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x3A5: /*REP MOVSL*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, EDI, EDI+3); - templ = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) break; - writememl(es,EDI,templ); if (cpu_state.abrt) break; - if (flags&D_FLAG) { EDI-=4; ESI-=4; } - else { EDI+=4; ESI+=4; } - c--; - cycles-=(is486)?3:4; - ins++; - reads_l++; writes_l++; total_cycles += is486 ? 3 : 4; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0xA6: case 0x1A6: /*REP CMPSB*/ - tempz = (fv) ? 1 : 0; - if ((c>0) && (fv==tempz)) - { - temp = readmemb(cpu_state.ea_seg->base, SI); - temp2=readmemb(es,DI); - if (cpu_state.abrt) { flags=of; break; } - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - c--; - cycles-=(is486)?7:9; - reads += 2; total_cycles += is486 ? 7 : 9; - setsub8(temp,temp2); - tempz = (ZF_SET()) ? 1 : 0; - } - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x2A6: case 0x3A6: /*REP CMPSB*/ - tempz = (fv) ? 1 : 0; - if ((c>0) && (fv==tempz)) - { - temp = readmemb(cpu_state.ea_seg->base, ESI); - temp2=readmemb(es,EDI); - if (cpu_state.abrt) { flags=of; break; } - if (flags&D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } - c--; - cycles-=(is486)?7:9; - reads += 2; total_cycles += is486 ? 7 : 9; - setsub8(temp,temp2); - tempz = (ZF_SET()) ? 1 : 0; - } - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0xA7: /*REP CMPSW*/ - tempz = (fv) ? 1 : 0; - if ((c>0) && (fv==tempz)) - { - tempw = readmemw(cpu_state.ea_seg->base, SI); - tempw2=readmemw(es,DI); - - if (cpu_state.abrt) { flags=of; break; } - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - c--; - cycles-=(is486)?7:9; - reads += 2; total_cycles += is486 ? 7 : 9; - setsub16(tempw,tempw2); - tempz = (ZF_SET()) ? 1 : 0; - } - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x1A7: /*REP CMPSL*/ - tempz = (fv) ? 1 : 0; - if ((c>0) && (fv==tempz)) - { - templ = readmeml(cpu_state.ea_seg->base, SI); - templ2=readmeml(es,DI); - if (cpu_state.abrt) { flags=of; break; } - if (flags&D_FLAG) { DI-=4; SI-=4; } - else { DI+=4; SI+=4; } - c--; - cycles-=(is486)?7:9; - reads_l += 2; total_cycles += is486 ? 7 : 9; - setsub32(templ,templ2); - tempz = (ZF_SET()) ? 1 : 0; - } - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x2A7: /*REP CMPSW*/ - tempz = (fv) ? 1 : 0; - if ((c>0) && (fv==tempz)) - { - tempw = readmemw(cpu_state.ea_seg->base, ESI); - tempw2=readmemw(es,EDI); - if (cpu_state.abrt) { flags=of; break; } - if (flags&D_FLAG) { EDI-=2; ESI-=2; } - else { EDI+=2; ESI+=2; } - c--; - cycles-=(is486)?7:9; - reads += 2; total_cycles += is486 ? 7 : 9; - setsub16(tempw,tempw2); - tempz = (ZF_SET()) ? 1 : 0; - } - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x3A7: /*REP CMPSL*/ - tempz = (fv) ? 1 : 0; - if ((c>0) && (fv==tempz)) - { - templ = readmeml(cpu_state.ea_seg->base, ESI); - templ2=readmeml(es,EDI); - if (cpu_state.abrt) { flags=of; break; } - if (flags&D_FLAG) { EDI-=4; ESI-=4; } - else { EDI+=4; ESI+=4; } - c--; - cycles-=(is486)?7:9; - reads_l += 2; total_cycles += is486 ? 7 : 9; - setsub32(templ,templ2); - tempz = (ZF_SET()) ? 1 : 0; - } - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - - case 0xAA: case 0x1AA: /*REP STOSB*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, DI, DI); - writememb(es,DI,AL); - if (cpu_state.abrt) break; - if (flags&D_FLAG) DI--; - else DI++; - c--; - cycles-=(is486)?4:5; - writes++; total_cycles += is486 ? 4 : 5; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x2AA: case 0x3AA: /*REP STOSB*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, EDI, EDI); - writememb(es,EDI,AL); - if (cpu_state.abrt) break; - if (flags&D_FLAG) EDI--; - else EDI++; - c--; - cycles-=(is486)?4:5; - writes++; total_cycles += is486 ? 4 : 5; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0xAB: /*REP STOSW*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, DI, DI+1); - writememw(es,DI,AX); - if (cpu_state.abrt) break; - if (flags&D_FLAG) DI-=2; - else DI+=2; - c--; - cycles-=(is486)?4:5; - writes++; total_cycles += is486 ? 4 : 5; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x2AB: /*REP STOSW*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, EDI, EDI+1); - writememw(es,EDI,AX); - if (cpu_state.abrt) break; - if (flags&D_FLAG) EDI-=2; - else EDI+=2; - c--; - cycles-=(is486)?4:5; - writes++; total_cycles += is486 ? 4 : 5; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x1AB: /*REP STOSL*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, DI, DI+3); - writememl(es,DI,EAX); - if (cpu_state.abrt) break; - if (flags&D_FLAG) DI-=4; - else DI+=4; - c--; - cycles-=(is486)?4:5; - writes_l++; total_cycles += is486 ? 4 : 5; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x3AB: /*REP STOSL*/ - while (c > 0) - { - CHECK_WRITE_REP(&_es, EDI, EDI+3); - writememl(es,EDI,EAX); - if (cpu_state.abrt) break; - if (flags&D_FLAG) EDI-=4; - else EDI+=4; - c--; - cycles-=(is486)?4:5; - writes_l++; total_cycles += is486 ? 4 : 5; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0xAC: case 0x1AC: /*REP LODSB*/ - if (c>0) - { - AL = readmemb(cpu_state.ea_seg->base, SI); - if (cpu_state.abrt) break; - if (flags&D_FLAG) SI--; - else SI++; - c--; - cycles-=5; - reads++; total_cycles += 5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x2AC: case 0x3AC: /*REP LODSB*/ - if (c>0) - { - AL = readmemb(cpu_state.ea_seg->base, ESI); - if (cpu_state.abrt) break; - if (flags&D_FLAG) ESI--; - else ESI++; - c--; - cycles-=5; - reads++; total_cycles += 5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0xAD: /*REP LODSW*/ - if (c>0) - { - AX = readmemw(cpu_state.ea_seg->base, SI); - if (cpu_state.abrt) break; - if (flags&D_FLAG) SI-=2; - else SI+=2; - c--; - cycles-=5; - reads++; total_cycles += 5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x1AD: /*REP LODSL*/ - if (c>0) - { - EAX = readmeml(cpu_state.ea_seg->base, SI); - if (cpu_state.abrt) break; - if (flags&D_FLAG) SI-=4; - else SI+=4; - c--; - cycles-=5; - reads_l++; total_cycles += 5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x2AD: /*REP LODSW*/ - if (c>0) - { - AX = readmemw(cpu_state.ea_seg->base, ESI); - if (cpu_state.abrt) break; - if (flags&D_FLAG) ESI-=2; - else ESI+=2; - c--; - cycles-=5; - reads++; total_cycles += 5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0x3AD: /*REP LODSL*/ - if (c>0) - { - EAX = readmeml(cpu_state.ea_seg->base, ESI); - if (cpu_state.abrt) break; - if (flags&D_FLAG) ESI-=4; - else ESI+=4; - c--; - cycles-=5; - reads_l++; total_cycles += 5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } - else firstrepcycle=1; - break; - case 0xAE: case 0x1AE: /*REP SCASB*/ - cpu_notreps++; - tempz = (fv) ? 1 : 0; - while ((c > 0) && (fv == tempz)) - { - temp2=readmemb(es,DI); - if (cpu_state.abrt) { flags=of; break; } - setsub8(AL,temp2); - tempz = (ZF_SET()) ? 1 : 0; - if (flags&D_FLAG) DI--; - else DI++; - c--; - cycles-=(is486)?5:8; - reads++; total_cycles += is486 ? 5 : 8; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x2AE: case 0x3AE: /*REP SCASB*/ - cpu_notreps++; - tempz = (fv) ? 1 : 0; - while ((c > 0) && (fv == tempz)) - { - temp2=readmemb(es,EDI); - if (cpu_state.abrt) { flags=of; break; } - setsub8(AL,temp2); - tempz = (ZF_SET()) ? 1 : 0; - if (flags&D_FLAG) EDI--; - else EDI++; - c--; - cycles-=(is486)?5:8; - reads++; total_cycles += is486 ? 5 : 8; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0xAF: /*REP SCASW*/ - cpu_notreps++; - tempz = (fv) ? 1 : 0; - while ((c > 0) && (fv == tempz)) - { - tempw=readmemw(es,DI); - if (cpu_state.abrt) { flags=of; break; } - setsub16(AX,tempw); - tempz = (ZF_SET()) ? 1 : 0; - if (flags&D_FLAG) DI-=2; - else DI+=2; - c--; - cycles-=(is486)?5:8; - reads++; total_cycles += is486 ? 5 : 8; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x1AF: /*REP SCASL*/ - cpu_notreps++; - tempz = (fv) ? 1 : 0; - while ((c > 0) && (fv == tempz)) - { - templ=readmeml(es,DI); - if (cpu_state.abrt) { flags=of; break; } - setsub32(EAX,templ); - tempz = (ZF_SET()) ? 1 : 0; - if (flags&D_FLAG) DI-=4; - else DI+=4; - c--; - cycles-=(is486)?5:8; - reads_l++; total_cycles += is486 ? 5 : 8; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x2AF: /*REP SCASW*/ - cpu_notreps++; - tempz = (fv) ? 1 : 0; - while ((c > 0) && (fv == tempz)) - { - tempw=readmemw(es,EDI); - if (cpu_state.abrt) { flags=of; break; } - setsub16(AX,tempw); - tempz = (ZF_SET()) ? 1 : 0; - if (flags&D_FLAG) EDI-=2; - else EDI+=2; - c--; - cycles-=(is486)?5:8; - reads++; total_cycles += is486 ? 5 : 8; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - case 0x3AF: /*REP SCASL*/ - cpu_notreps++; - tempz = (fv) ? 1 : 0; - while ((c > 0) && (fv == tempz)) - { - templ=readmeml(es,EDI); - if (cpu_state.abrt) { flags=of; break; } - setsub32(EAX,templ); - tempz = (ZF_SET()) ? 1 : 0; - if (flags&D_FLAG) EDI-=4; - else EDI+=4; - c--; - cycles-=(is486)?5:8; - reads_l++; total_cycles += is486 ? 5 : 8; - ins++; - if (cycles < cycles_end) - break; - } - ins--; - if ((c>0) && (fv==tempz)) { cpu_state.pc=ipc; firstrepcycle=0; } - else firstrepcycle=1; - break; - - - default: - cpu_state.pc = ipc+1; - break; - } - if (rep32&0x200) ECX=c; - else CX=c; - CPU_BLOCK_END(); - PREFETCH_RUN(total_cycles, 1, -1, reads, reads_l, writes, writes_l, 0); - return cpu_state.abrt; -} - int xout=0; diff --git a/src/CPU/386_ops.h b/src/CPU/386_ops.h index 0217c384d..c1aa2ff66 100644 --- a/src/CPU/386_ops.h +++ b/src/CPU/386_ops.h @@ -1410,4 +1410,186 @@ OpFn OP_TABLE(386)[1024] = /*d0*/ opD0_a32, opD1_l_a32, opD2_a32, opD3_l_a32, opAAM, opAAD, opSETALC, opXLAT_a32, opESCAPE_d8_a32,opESCAPE_d9_a32,opESCAPE_da_a32,opESCAPE_db_a32,opESCAPE_dc_a32,opESCAPE_dd_a32,opESCAPE_de_a32,opESCAPE_df_a32, /*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX, /*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32, +}; + +OpFn OP_TABLE(REPE)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_w_a16,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_w_a16,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_w_a16,opGS_REPE_w_a16,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_E,opREP_CMPSW_a16_E,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_E,opREP_SCASW_a16_E, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_l_a16,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_l_a16,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_l_a16,opGS_REPE_l_a16,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_E,opREP_CMPSL_a16_E,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_E,opREP_SCASL_a16_E, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_w_a32,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_w_a32,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_w_a32,opGS_REPE_w_a32,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_E,opREP_CMPSW_a32_E,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_E,opREP_SCASW_a32_E, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_l_a32,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_l_a32,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_l_a32,opGS_REPE_l_a32,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_E,opREP_CMPSL_a32_E,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_E,opREP_SCASL_a32_E, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(REPNE)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_w_a16,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_w_a16,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_w_a16,opGS_REPNE_w_a16,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_NE,opREP_CMPSW_a16_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_NE,opREP_SCASW_a16_NE, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_l_a16,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_l_a16,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_l_a16,opGS_REPNE_l_a16,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_NE,opREP_CMPSL_a16_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_NE,opREP_SCASL_a16_NE, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_w_a32,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_w_a32,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_w_a32,opGS_REPNE_w_a32,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_NE,opREP_CMPSW_a32_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_NE,opREP_SCASW_a32_NE, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_l_a32,ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_l_a32,ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_l_a32,opGS_REPNE_l_a32,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_NE,opREP_CMPSL_a32_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_NE,opREP_SCASL_a32_NE, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; diff --git a/src/CPU/codegen_ops.c b/src/CPU/codegen_ops.c index 2bd6550e2..c91a0d9db 100644 --- a/src/CPU/codegen_ops.c +++ b/src/CPU/codegen_ops.c @@ -496,3 +496,97 @@ RecompOpFn recomp_opcodes_df[512] = /*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; + +RecompOpFn recomp_opcodes_REPE[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + +RecompOpFn recomp_opcodes_REPNE[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; diff --git a/src/CPU/codegen_ops.h b/src/CPU/codegen_ops.h index 36b21918e..bda54029a 100644 --- a/src/CPU/codegen_ops.h +++ b/src/CPU/codegen_ops.h @@ -10,6 +10,8 @@ extern RecompOpFn recomp_opcodes_dc[512]; extern RecompOpFn recomp_opcodes_dd[512]; extern RecompOpFn recomp_opcodes_de[512]; extern RecompOpFn recomp_opcodes_df[512]; +RecompOpFn recomp_opcodes_REPE[512]; +RecompOpFn recomp_opcodes_REPNE[512]; #define REG_EAX 0 #define REG_ECX 1 diff --git a/src/CPU/codegen_x86-64.c b/src/CPU/codegen_x86-64.c index 3ce22d95e..d174f8f48 100644 --- a/src/CPU/codegen_x86-64.c +++ b/src/CPU/codegen_x86-64.c @@ -1049,6 +1049,15 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t case 0xf0: /*LOCK*/ break; + case 0xf2: /*REPNE*/ + op_table = x86_dynarec_opcodes_REPNE; + recomp_op_table = recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPE; + recomp_op_table = recomp_opcodes_REPE; + break; + default: goto generate_call; } @@ -1089,6 +1098,13 @@ generate_call: codegen_block_ins = 0; } } + + if ((op_table == x86_opcodes_REPNE || op_table == x86_opcodes_REPE) && !op_table[opcode | op_32]) + { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); diff --git a/src/CPU/codegen_x86.c b/src/CPU/codegen_x86.c index f747fd262..cf5492040 100644 --- a/src/CPU/codegen_x86.c +++ b/src/CPU/codegen_x86.c @@ -1977,6 +1977,15 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t case 0xf0: /*LOCK*/ break; + + case 0xf2: /*REPNE*/ + op_table = x86_dynarec_opcodes_REPNE; + recomp_op_table = recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPE; + recomp_op_table = recomp_opcodes_REPE; + break; default: goto generate_call; @@ -2030,6 +2039,12 @@ generate_call: #endif } + if ((op_table == x86_opcodes_REPNE || op_table == x86_opcodes_REPE) && !op_table[opcode | op_32]) + { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); diff --git a/src/CPU/cpu.c b/src/CPU/cpu.c index 2c07c438e..f8f4c9c76 100644 --- a/src/CPU/cpu.c +++ b/src/CPU/cpu.c @@ -48,6 +48,8 @@ OpFn *x86_dynarec_opcodes_de_a16; OpFn *x86_dynarec_opcodes_de_a32; OpFn *x86_dynarec_opcodes_df_a16; OpFn *x86_dynarec_opcodes_df_a32; +OpFn *x86_dynarec_opcodes_REPE; +OpFn *x86_dynarec_opcodes_REPNE; OpFn *x86_opcodes; OpFn *x86_opcodes_0f; @@ -67,6 +69,8 @@ OpFn *x86_opcodes_de_a16; OpFn *x86_opcodes_de_a32; OpFn *x86_opcodes_df_a16; OpFn *x86_opcodes_df_a32; +OpFn *x86_opcodes_REPE; +OpFn *x86_opcodes_REPNE; enum { @@ -679,6 +683,10 @@ void cpu_set() pclog("is486 - %i %i\n",is486,cpu_s->cpu_type); x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); + x86_opcodes_REPE = ops_REPE; + x86_opcodes_REPNE = ops_REPNE; + x86_dynarec_opcodes_REPE = dynarec_ops_REPE; + x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE; if (hasfpu) { diff --git a/src/CPU/x86_ops.h b/src/CPU/x86_ops.h index 389420921..7cce21c61 100644 --- a/src/CPU/x86_ops.h +++ b/src/CPU/x86_ops.h @@ -26,6 +26,8 @@ extern OpFn *x86_dynarec_opcodes_de_a16; extern OpFn *x86_dynarec_opcodes_de_a32; extern OpFn *x86_dynarec_opcodes_df_a16; extern OpFn *x86_dynarec_opcodes_df_a32; +extern OpFn *x86_dynarec_opcodes_REPE; +extern OpFn *x86_dynarec_opcodes_REPNE; extern OpFn dynarec_ops_286[1024]; extern OpFn dynarec_ops_286_0f[1024]; @@ -87,6 +89,9 @@ extern OpFn dynarec_ops_fpu_686_db_a32[256]; extern OpFn dynarec_ops_fpu_686_df_a16[256]; extern OpFn dynarec_ops_fpu_686_df_a32[256]; +extern OpFn dynarec_ops_REPE[1024]; +extern OpFn dynarec_ops_REPNE[1024]; + extern OpFn *x86_opcodes; extern OpFn *x86_opcodes_0f; extern OpFn *x86_opcodes_d8_a16; @@ -105,6 +110,8 @@ extern OpFn *x86_opcodes_de_a16; extern OpFn *x86_opcodes_de_a32; extern OpFn *x86_opcodes_df_a16; extern OpFn *x86_opcodes_df_a32; +extern OpFn *x86_opcodes_REPE; +extern OpFn *x86_opcodes_REPNE; extern OpFn ops_286[1024]; extern OpFn ops_286_0f[1024]; @@ -167,4 +174,7 @@ extern OpFn ops_fpu_686_db_a32[256]; extern OpFn ops_fpu_686_df_a16[256]; extern OpFn ops_fpu_686_df_a32[256]; +extern OpFn ops_REPE[1024]; +extern OpFn ops_REPNE[1024]; + #endif /*_X86_OPS_H*/ diff --git a/src/CPU/x86_ops_prefix.h b/src/CPU/x86_ops_prefix.h index c5d5b3042..8265c19f1 100644 --- a/src/CPU/x86_ops_prefix.h +++ b/src/CPU/x86_ops_prefix.h @@ -1,4 +1,4 @@ -#define op_seg(name, seg) \ +#define op_seg(name, seg, opcode_table, normal_opcode_table) \ static int op ## name ## _w_a16(uint32_t fetchdat) \ { \ fetchdat = fastreadl(cs + cpu_state.pc); \ @@ -10,7 +10,9 @@ static int op ## name ## _w_a16(uint32_t fetchdat) \ CLOCK_CYCLES(4); \ PREFETCH_PREFIX(); \ \ - return x86_opcodes[fetchdat & 0xff](fetchdat >> 8); \ + if (opcode_table[fetchdat & 0xff]) \ + return opcode_table[fetchdat & 0xff](fetchdat >> 8); \ + return normal_opcode_table[fetchdat & 0xff](fetchdat >> 8); \ } \ \ static int op ## name ## _l_a16(uint32_t fetchdat) \ @@ -24,7 +26,9 @@ static int op ## name ## _l_a16(uint32_t fetchdat) \ CLOCK_CYCLES(4); \ PREFETCH_PREFIX(); \ \ - return x86_opcodes[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ + if (opcode_table[(fetchdat & 0xff) | 0x100]) \ + return opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ + return normal_opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ } \ \ static int op ## name ## _w_a32(uint32_t fetchdat) \ @@ -38,7 +42,9 @@ static int op ## name ## _w_a32(uint32_t fetchdat) \ CLOCK_CYCLES(4); \ PREFETCH_PREFIX(); \ \ - return x86_opcodes[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ + if (opcode_table[(fetchdat & 0xff) | 0x200]) \ + return opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ + return normal_opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ } \ \ static int op ## name ## _l_a32(uint32_t fetchdat) \ @@ -52,15 +58,31 @@ static int op ## name ## _l_a32(uint32_t fetchdat) \ CLOCK_CYCLES(4); \ PREFETCH_PREFIX(); \ \ - return x86_opcodes[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ + if (opcode_table[(fetchdat & 0xff) | 0x300]) \ + return opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ + return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ } -op_seg(CS, _cs) -op_seg(DS, _ds) -op_seg(ES, _es) -op_seg(FS, _fs) -op_seg(GS, _gs) -op_seg(SS, _ss) +op_seg(CS, _cs, x86_opcodes, x86_opcodes) +op_seg(DS, _ds, x86_opcodes, x86_opcodes) +op_seg(ES, _es, x86_opcodes, x86_opcodes) +op_seg(FS, _fs, x86_opcodes, x86_opcodes) +op_seg(GS, _gs, x86_opcodes, x86_opcodes) +op_seg(SS, _ss, x86_opcodes, x86_opcodes) + +op_seg(CS_REPE, _cs, x86_opcodes_REPE, x86_opcodes) +op_seg(DS_REPE, _ds, x86_opcodes_REPE, x86_opcodes) +op_seg(ES_REPE, _es, x86_opcodes_REPE, x86_opcodes) +op_seg(FS_REPE, _fs, x86_opcodes_REPE, x86_opcodes) +op_seg(GS_REPE, _gs, x86_opcodes_REPE, x86_opcodes) +op_seg(SS_REPE, _ss, x86_opcodes_REPE, x86_opcodes) + +op_seg(CS_REPNE, _cs, x86_opcodes_REPNE, x86_opcodes) +op_seg(DS_REPNE, _ds, x86_opcodes_REPNE, x86_opcodes) +op_seg(ES_REPNE, _es, x86_opcodes_REPNE, x86_opcodes) +op_seg(FS_REPNE, _fs, x86_opcodes_REPNE, x86_opcodes) +op_seg(GS_REPNE, _gs, x86_opcodes_REPNE, x86_opcodes) +op_seg(SS_REPNE, _ss, x86_opcodes_REPNE, x86_opcodes) static int op_66(uint32_t fetchdat) /*Data size select*/ { @@ -84,3 +106,56 @@ static int op_67(uint32_t fetchdat) /*Address size select*/ PREFETCH_PREFIX(); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } + +static int op_66_REPE(uint32_t fetchdat) /*Data size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int op_67_REPE(uint32_t fetchdat) /*Address size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int op_66_REPNE(uint32_t fetchdat) /*Data size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int op_67_REPNE(uint32_t fetchdat) /*Address size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} diff --git a/src/CPU/x86_ops_rep.h b/src/CPU/x86_ops_rep.h index dafdbff7c..140f60916 100644 --- a/src/CPU/x86_ops_rep.h +++ b/src/CPU/x86_ops_rep.h @@ -1,12 +1,629 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ +static int opREP_INSB_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) \ + { \ + uint8_t temp; \ + \ + check_io_perm(DX); \ + temp = inb(DX); \ + writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) DEST_REG--; \ + else DEST_REG++; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; writes++; total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_INSW_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) \ + { \ + uint16_t temp; \ + \ + check_io_perm(DX); \ + check_io_perm(DX+1); \ + temp = inw(DX); \ + writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) DEST_REG -= 2; \ + else DEST_REG += 2; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; writes++; total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_INSL_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) \ + { \ + uint32_t temp; \ + \ + check_io_perm(DX); \ + check_io_perm(DX+1); \ + check_io_perm(DX+2); \ + check_io_perm(DX+3); \ + temp = inl(DX); \ + writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) DEST_REG -= 4; \ + else DEST_REG += 4; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; writes++; total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ + \ +static int opREP_OUTSB_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) \ + { \ + uint8_t temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + check_io_perm(DX); \ + outb(DX, temp); \ + if (flags & D_FLAG) SRC_REG--; \ + else SRC_REG++; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; writes++; total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_OUTSW_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) \ + { \ + uint16_t temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + check_io_perm(DX); \ + check_io_perm(DX+1); \ + outw(DX, temp); \ + if (flags & D_FLAG) SRC_REG -= 2; \ + else SRC_REG += 2; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; writes++; total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_OUTSL_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) \ + { \ + uint32_t temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + check_io_perm(DX); \ + check_io_perm(DX+1); \ + check_io_perm(DX+2); \ + check_io_perm(DX+3); \ + outl(DX, temp); \ + if (flags & D_FLAG) SRC_REG -= 4; \ + else SRC_REG += 4; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; writes++; total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ + \ +static int opREP_MOVSB_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + uint8_t temp; \ + \ + CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ + else { DEST_REG++; SRC_REG++; } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + ins++; \ + reads++; writes++; total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + ins--; \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_MOVSW_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + uint16_t temp; \ + \ + CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ + else { DEST_REG += 2; SRC_REG += 2; } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + ins++; \ + reads++; writes++; total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + ins--; \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_MOVSL_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + uint32_t temp; \ + \ + CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ + else { DEST_REG += 4; SRC_REG += 4; } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + ins++; \ + reads++; writes++; total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + ins--; \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ + \ + \ +static int opREP_STOSB_ ## size(uint32_t fetchdat) \ +{ \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + writememb(es, DEST_REG, AL); if (cpu_state.abrt) return 1; \ + if (flags & D_FLAG) DEST_REG--; \ + else DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; total_cycles += is486 ? 4 : 5; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_STOSW_ ## size(uint32_t fetchdat) \ +{ \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+1); \ + writememw(es, DEST_REG, AX); if (cpu_state.abrt) return 1; \ + if (flags & D_FLAG) DEST_REG -= 2; \ + else DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; total_cycles += is486 ? 4 : 5; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_STOSL_ ## size(uint32_t fetchdat) \ +{ \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+3); \ + writememl(es, DEST_REG, EAX); if (cpu_state.abrt) return 1; \ + if (flags & D_FLAG) DEST_REG -= 4; \ + else DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; total_cycles += is486 ? 4 : 5; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ + \ +static int opREP_LODSB_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + if (flags & D_FLAG) SRC_REG--; \ + else SRC_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; total_cycles += is486 ? 4 : 5; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_LODSW_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + if (flags & D_FLAG) SRC_REG -= 2; \ + else SRC_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; total_cycles += is486 ? 4 : 5; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_LODSL_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + while (CNT_REG > 0) \ + { \ + EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + if (flags & D_FLAG) SRC_REG -= 4; \ + else SRC_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; total_cycles += is486 ? 4 : 5; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if (CNT_REG > 0) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ + + +#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ +static int opREP_CMPSB_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0, tempz; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + uint8_t temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + uint8_t temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ + else { DEST_REG++; SRC_REG++; } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; total_cycles += is486 ? 7 : 9; \ + setsub8(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_CMPSW_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0, tempz; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + uint16_t temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + uint16_t temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ + else { DEST_REG += 2; SRC_REG += 2; } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; total_cycles += is486 ? 7 : 9; \ + setsub16(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_CMPSL_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0, tempz; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + uint32_t temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + uint32_t temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \ + \ + if (flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ + else { DEST_REG += 4; SRC_REG += 4; } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; total_cycles += is486 ? 7 : 9; \ + setsub32(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ + \ +static int opREP_SCASB_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + tempz = FV; \ + while ((CNT_REG > 0) && (FV == tempz)) \ + { \ + uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\ + setsub8(AL, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (flags & D_FLAG) DEST_REG--; \ + else DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; total_cycles += is486 ? 5 : 8; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + ins--; \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_SCASW_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + tempz = FV; \ + while ((CNT_REG > 0) && (FV == tempz)) \ + { \ + uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\ + setsub16(AX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (flags & D_FLAG) DEST_REG -= 2; \ + else DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; total_cycles += is486 ? 5 : 8; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + ins--; \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} \ +static int opREP_SCASL_ ## size(uint32_t fetchdat) \ +{ \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + \ + tempz = FV; \ + while ((CNT_REG > 0) && (FV == tempz)) \ + { \ + uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\ + setsub32(EAX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (flags & D_FLAG) DEST_REG -= 4; \ + else DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; total_cycles += is486 ? 5 : 8; \ + ins++; \ + if (cycles < cycles_end) \ + break; \ + } \ + ins--; \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) \ + { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ +} + +REP_OPS(a16, CX, SI, DI) +REP_OPS(a32, ECX, ESI, EDI) +REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0) +REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1) +REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0) +REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) + static int opREPNE(uint32_t fetchdat) { - return rep386(0); + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } static int opREPE(uint32_t fetchdat) { - return rep386(1); -} + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} diff --git a/src/ibm.h b/src/ibm.h index b4fac859b..61b662ebc 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -775,7 +775,6 @@ extern void pmodeiret(int is32); extern void port_92_clear_reset(void); extern uint8_t readdacfifo(void); extern void refreshread(void); -extern int rep386(int fv); extern void resetmcr(void); extern void resetpchard_close(void); extern void resetpchard_init(void); From 96707424355ed8df0a6fc8912adab9dd2e4650e4 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 21 Jul 2017 15:27:29 +0200 Subject: [PATCH 19/82] Made Mouse Systems Mouse a 3-button Mouse. --- src/mouse_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 208f95378..d50b71d2e 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -413,7 +413,7 @@ mouse_t mouse_msystems = { "Mouse Systems Mouse (serial)", "mssystems", - MOUSE_TYPE_MSYSTEMS, + MOUSE_TYPE_MSYSTEMS | MOUSE_TYPE_3BUTTON, mouse_serial_msystems_init, mouse_serial_close, mouse_serial_msystems_poll From 6332864e4528a2d71aa3b82c97ca7e124ef33b52 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Jul 2017 10:58:12 +0200 Subject: [PATCH 20/82] The emulator no longer waits for blit on window resize, fixes both the freeze on window move and the EGA half size problem on XT machines. --- src/VIDEO/vid_ega.c | 18 ++++++++++-------- src/WIN/win.c | 1 - 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/VIDEO/vid_ega.c b/src/VIDEO/vid_ega.c index 10148ad55..49cf3358a 100644 --- a/src/VIDEO/vid_ega.c +++ b/src/VIDEO/vid_ega.c @@ -532,13 +532,16 @@ void ega_poll(void *p) } else if (!(ega->gdcreg[6] & 1)) { - if (ega_jega_enabled(ega)) + if (fullchange) { - ega_render_text_jega(ega, drawcursor); - } - else - { - ega_render_text_standard(ega, drawcursor); + if (ega_jega_enabled(ega)) + { + ega_render_text_jega(ega, drawcursor); + } + else + { + ega_render_text_standard(ega, drawcursor); + } } } else @@ -639,7 +642,7 @@ void ega_poll(void *p) if (ega->interlace && !ega->oddeven) ega->lastline++; if (ega->interlace && ega->oddeven) ega->firstline--; - if ((x != xsize || (ega->lastline - ega->firstline) != ysize) || update_overscan) + if ((x != xsize || (ega->lastline - ega->firstline + 1) != ysize) || update_overscan) { xsize = x; ysize = ega->lastline - ega->firstline + 1; @@ -763,7 +766,6 @@ void ega_poll(void *p) ega->sc = 0; ega->dispon = 1; ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; - ega->displine = 0; ega->scrollcache = ega->attrregs[0x13] & 7; } if (ega->sc == (ega->crtc[10] & 31)) diff --git a/src/WIN/win.c b/src/WIN/win.c index 38649ac7a..f368b56f4 100644 --- a/src/WIN/win.c +++ b/src/WIN/win.c @@ -334,7 +334,6 @@ void mainthread(LPVOID param) if (!video_fullscreen && win_doresize && (winsizex > 0) && (winsizey > 0)) { - video_wait_for_blit(); SendMessage(hwndStatus, SB_GETBORDERS, 0, (LPARAM) sb_borders); GetWindowRect(ghwnd, &r); MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); From 2d13d7cb20b944025174d5d54762a9a47a5b3b4b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Jul 2017 11:51:00 +0200 Subject: [PATCH 21/82] ISO mounting code now defaults to 2048 bytes per sector Mode 1 if it can not read the PVD rather than refusing to load the ISO, fixes mounting of Apple Rhapsody ISO's. --- src/cdrom_dosbox.cpp | 6 +++++- src/cdrom_dosbox.h | 2 ++ src/cdrom_image.cc | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cdrom_dosbox.cpp b/src/cdrom_dosbox.cpp index 4def610ca..0b2ea24c6 100644 --- a/src/cdrom_dosbox.cpp +++ b/src/cdrom_dosbox.cpp @@ -247,7 +247,11 @@ bool CDROM_Interface_Image::LoadIsoFile(char* filename) } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) { track.sectorSize = RAW_SECTOR_SIZE; track.mode2 = true; - } else return false; + } else { + /* Unknown mode: Assume regular 2048-byte sectors, this is needed so Apple Rhapsody ISO's can be mounted. */ + track.sectorSize = COOKED_SECTOR_SIZE; + track.mode2 = false; + } track.length = track.file->getLength() / track.sectorSize; tracks.push_back(track); diff --git a/src/cdrom_dosbox.h b/src/cdrom_dosbox.h index dc88bbe45..8a6364f48 100644 --- a/src/cdrom_dosbox.h +++ b/src/cdrom_dosbox.h @@ -171,4 +171,6 @@ typedef std::vector::iterator track_it; std::string mcn; }; +void cdrom_image_log(const char *format, ...); + #endif /* __CDROM_INTERFACE__ */ diff --git a/src/cdrom_image.cc b/src/cdrom_image.cc index a7fee4477..42d40be77 100644 --- a/src/cdrom_image.cc +++ b/src/cdrom_image.cc @@ -988,6 +988,7 @@ int image_open(uint8_t id, wchar_t *fn) wcstombs(afn, fn, sizeof(afn)); if (!cdimg[id]->SetDevice(afn, false)) { + pclog("Image failed to load\n"); image_close(id); cdrom_set_null_handler(id); return 1; From bf8942b55eb9562cebf8f8bb7df663444d5d058e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Jul 2017 09:36:50 +0200 Subject: [PATCH 22/82] Configuration variable and section delete functions now only set the first character of the name to ASCII 0x00 rather than zeroing the entire array, fixes hard disk corruption bug on floppy mount. --- src/config.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 9821b3f5a..2ebc6d3da 100644 --- a/src/config.c +++ b/src/config.c @@ -471,7 +471,8 @@ void config_delete_var(char *head, char *name) if (!entry) return; - memset(entry->name, 0, strlen(entry->name)); + /* memset(entry->name, 0, strlen(entry->name)); */ + entry->name[0] = 0; return; } @@ -488,7 +489,8 @@ void config_delete_section_if_empty(char *head) if (entries_num(section) == 0) { - memset(section->name, 0, strlen(section->name)); + /* memset(section->name, 0, strlen(section->name)); */ + section->name[0] = 0; } return; @@ -742,7 +744,7 @@ void config_save(wchar_t *fn) while (current_entry) { - if(strlen(current_entry->name) > 0) + if(current_entry->name[0]) { mbstowcs(wname, current_entry->name, strlen(current_entry->name) + 1); if (current_entry->wdata[0] == L'\0') From ff23ccb2a22094928fb7c8c5d24677f56b5187a3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Jul 2017 12:04:39 +0200 Subject: [PATCH 23/82] Reorganized several resource strings; Added Microsoft serial wheel mouse emulation; AWE32 improvements from JosepMa's PCem branch; Applied REP invalid instruction ignore patch from Greatpsycho; Slightly reordered the list of emulated mice. --- src/CPU/386_ops.h | 267 +++-- src/NETWORK/network.c | 2 +- src/SOUND/snd_emu8k.c | 1923 +++++++++++++++++++++++++------ src/SOUND/snd_emu8k.h | 369 +++++- src/WIN/86Box.rc | 188 +-- src/WIN/plat_ui.h | 4 + src/WIN/resource.h | 153 +-- src/WIN/win.c | 96 +- src/WIN/win_ddraw_screenshot.cc | 2 +- src/WIN/win_language.c | 128 +- src/WIN/win_settings.c | 204 ++-- src/config.c | 8 +- src/mouse.c | 19 +- src/mouse.h | 23 +- src/mouse_serial.c | 66 +- src/mouse_serial.h | 3 +- 16 files changed, 2481 insertions(+), 974 deletions(-) diff --git a/src/CPU/386_ops.h b/src/CPU/386_ops.h index c1aa2ff66..71a6f1e4b 100644 --- a/src/CPU/386_ops.h +++ b/src/CPU/386_ops.h @@ -227,6 +227,17 @@ static int op0F_l_a32(uint32_t fetchdat) return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); } +static int opREP_ignore(uint32_t fetchdat) +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) return 0; + cpu_state.pc++; + + CLOCK_CYCLES((is486) ? 1 : 3); + PREFETCH_PREFIX(); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} + OpFn OP_TABLE(286_0f)[1024] = { /*16-bit data, 16-bit addr*/ @@ -1416,180 +1427,180 @@ OpFn OP_TABLE(REPE)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_w_a16,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_w_a16,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_w_a16,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_w_a16,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_w_a16,opGS_REPE_w_a16,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_w_a16,opGS_REPE_w_a16,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_E,opREP_CMPSW_a16_E,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_E,opREP_SCASW_a16_E, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_E,opREP_CMPSW_a16_E,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_E,opREP_SCASW_a16_E, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_l_a16,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_l_a16,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_l_a16,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_l_a16,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_l_a16,opGS_REPE_l_a16,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_l_a16,opGS_REPE_l_a16,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_E,opREP_CMPSL_a16_E,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_E,opREP_SCASL_a16_E, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_E,opREP_CMPSL_a16_E,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_E,opREP_SCASL_a16_E, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_w_a32,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_w_a32,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_w_a32,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_w_a32,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_w_a32,opGS_REPE_w_a32,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_w_a32,opGS_REPE_w_a32,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_E,opREP_CMPSW_a32_E,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_E,opREP_SCASW_a32_E, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_E,opREP_CMPSW_a32_E,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_E,opREP_SCASW_a32_E, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPE_l_a32,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPE_l_a32,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_l_a32,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_l_a32,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPE_l_a32,opGS_REPE_l_a32,op_66_REPE, op_67_REPE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_l_a32,opGS_REPE_l_a32,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_E,opREP_CMPSL_a32_E,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_E,opREP_SCASL_a32_E, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_E,opREP_CMPSL_a32_E,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_E,opREP_SCASL_a32_E, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, }; OpFn OP_TABLE(REPNE)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_w_a16,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_w_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_w_a16,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_w_a16,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_w_a16,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_w_a16,opGS_REPNE_w_a16,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_w_a16,opGS_REPNE_w_a16,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_NE,opREP_CMPSW_a16_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_NE,opREP_SCASW_a16_NE, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_NE,opREP_CMPSW_a16_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_NE,opREP_SCASW_a16_NE, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_l_a16,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_l_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_l_a16,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_l_a16,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_l_a16,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_l_a16,opGS_REPNE_l_a16,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_l_a16,opGS_REPNE_l_a16,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_NE,opREP_CMPSL_a16_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_NE,opREP_SCASL_a16_NE, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_NE,opREP_CMPSL_a16_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_NE,opREP_SCASL_a16_NE, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_w_a32,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_w_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_w_a32,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_w_a32,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_w_a32,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_w_a32,opGS_REPNE_w_a32,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_w_a32,opGS_REPNE_w_a32,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_NE,opREP_CMPSW_a32_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_NE,opREP_SCASW_a32_NE, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_NE,opREP_CMPSW_a32_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_NE,opREP_SCASW_a32_NE, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opES_REPNE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCS_REPNE_l_a32,ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSS_REPNE_l_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opDS_REPNE_l_a32,ILLEGAL, +/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_l_a32,opREP_ignore, +/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_l_a32,opREP_ignore, -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opFS_REPNE_l_a32,opGS_REPNE_l_a32,op_66_REPNE, op_67_REPNE, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_l_a32,opGS_REPNE_l_a32,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, +/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_NE,opREP_CMPSL_a32_NE,ILLEGAL, ILLEGAL, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_NE,opREP_SCASL_a32_NE, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_NE,opREP_CMPSL_a32_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_NE,opREP_SCASL_a32_NE, +/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, }; diff --git a/src/NETWORK/network.c b/src/NETWORK/network.c index 87d2613ac..1534d047f 100644 --- a/src/NETWORK/network.c +++ b/src/NETWORK/network.c @@ -111,7 +111,7 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx) case NET_TYPE_PCAP: ret = network_pcap_setup(mac, rx, dev); if (ret < 0) { - plat_msgbox_error(IDS_2219); + plat_msgbox_error(IDS_2139); network_type = NET_TYPE_NONE; } break; diff --git a/src/SOUND/snd_emu8k.c b/src/SOUND/snd_emu8k.c index c9982de11..af4c7cbbf 100644 --- a/src/SOUND/snd_emu8k.c +++ b/src/SOUND/snd_emu8k.c @@ -3,6 +3,7 @@ freq = 2^((in - 0xe000) / 4096)*/ /*LFO - lowest (0.042 Hz) = 2^20 steps = 1048576 highest (10.72 Hz) = 2^12 steps = 4096*/ +#include #include #include #include "../ibm.h" @@ -14,92 +15,455 @@ #include "sound.h" #include "snd_emu8k.h" +#define FILTER_INITIAL +/* #define FILTER_MOOG */ +/* #define FILTER_CONSTANT */ + + +/* #define EMU8K_DEBUG_REGISTERS */ + +char *PORT_NAMES[][8]={ + /* Data 0 ( 0x620/0x622) */ + { /* Register 0 */ + "AWE_CPF", + /* Register 1 */ + "AWE_PTRX", + /* Register 2 */ + "AWE_CVCF", + /* Register 3 */ + "AWE_VTFT", + /* Register 4 */ + "Unk-620-4", + /* Register 5 */ + "Unk-620-5", + /* Register 6 */ + "AWE_PSST", + /* Register 7 */ + "AWE_CSL", + }, + /* Data 1 0xA20 */ + { /* Register 0 */ + "AWE_CCCA", + /* Register 1 */ + 0, + /* + * + "AWE_HWCF4" + "AWE_HWCF5" + "AWE_HWCF6" + "AWE_HWCF7" + "AWE_SMALR" + "AWE_SMARR" + "AWE_SMALW" + "AWE_SMARW" + "AWE_SMLD" + "AWE_SMRD" + "AWE_WC" + "AWE_HWCF1" + "AWE_HWCF2" + "AWE_HWCF3" + */ + /* Register 2 */ + 0, /* "AWE_INIT1", */ + /* Register 3 */ + 0, /* "AWE_INIT3", */ + /* Register 4 */ + "AWE_ENVVOL", + /* Register 5 */ + "AWE_DCYSUSV", + /* Register 6 */ + "AWE_ENVVAL", + /* Register 7 */ + "AWE_DCYSUS", + }, + /* Data 2 0xA22 */ + { /* Register 0 */ + "AWE_CCCA", + /* Register 1 */ + 0, + /* Register 2 */ + 0, /* "AWE_INIT2", */ + /* Register 3 */ + 0, /* "AWE_INIT4", */ + /* Register 4 */ + "AWE_ATKHLDV", + /* Register 5 */ + "AWE_LFO1VAL", + /* Register 6 */ + "AWE_ATKHLD", + /* Register 7 */ + "AWE_LFO2VAL", + }, + /* Data 3 0xE20 */ + { /* Register 0 */ + "AWE_IP", + /* Register 1 */ + "AWE_IFATN", + /* Register 2 */ + "AWE_PEFE", + /* Register 3 */ + "AWE_FMMOD", + /* Register 4 */ + "AWE_TREMFRQ", + /* Register 5 */ + "AWE_FM2FRQ2", + /* Register 6 */ + 0, + /* Register 7 */ + 0, + }, +}; enum { ENV_STOPPED = 0, - ENV_ATTACK = 1, - ENV_DECAY = 2, - ENV_SUSTAIN = 3, - ENV_RELEASE = 4 + ENV_DELAY = 1, + ENV_ATTACK = 2, + ENV_HOLD = 3, + /* ENV_DECAY = 4, */ + ENV_SUSTAIN = 5, + /* ENV_RELEASE = 6, */ + ENV_RAMP_DOWN = 7, + ENV_RAMP_UP = 8 }; + +static int random_helper = 0; +int dmareadbit = 0; +int dmawritebit = 0; + + +/* cubic and linear tables resolution. Note: higher than 10 does not improve the result. */ +#define CUBIC_RESOLUTION_LOG 10 +#define CUBIC_RESOLUTION (1<> 15 to move back to +/-1 range). */ +static int32_t lfotable[65536]; +/* Table to transform the speed parameter to emu8k_mem_internal_t range. */ +static int64_t lfofreqtospeed[256]; -#define READ16(addr, var) switch ((addr) & 2) \ + +/* these lines come from the awe32faq, describing the NRPN control for the initial filter + where it describes a linear increment filter instead of an octave-incremented one. + NRPN LSB 21 (Initial Filter Cutoff) + Range : [0, 127] + Unit : 62Hz + Filter cutoff from 100Hz to 8000Hz */ + +/* This table comes from the awe32faq, describing the NRPN control for the filter Q. + I don't know if is meant to be interpreted as the actual measured output of the + filter or what. Especially, I don't understand the "low" and "high" ranges. + What is otherwise documented is that the Q ranges from 0dB to 24dB and the attenuation + is half of the Q ( i.e. for 12dB Q, attenuate the input signal with -6dB) */ +/*InitialFilterCutoff = RegisterValue*31.25Hz+100Hz */ +/*Coeff Low Fc(Hz)Low Q(dB)High Fc(kHz)High Q(dB)DC Attenuation(dB) +0 92 5 Flat Flat -0.0 +1 93 6 8.5 0.5 -0.5 +2 94 8 8.3 1 -1.2 +3 95 10 8.2 2 -1.8 +4 96 11 8.1 3 -2.5 +5 97 13 8.0 4 -3.3 +6 98 14 7.9 5 -4.1 +7 99 16 7.8 6 -5.5 +8 100 17 7.7 7 -6.0 +9 100 19 7.5 9 -6.6 +10 100 20 7.4 10 -7.2 +11 100 22 7.3 11 -7.9 +12 100 23 7.2 13 -8.5 +13 100 25 7.1 15 -9.3 +14 100 26 7.1 16 -10.1 +15 100 28 7.0 18 -11.0 +*/ +/* Attenuation as above, codified in amplitude, and Q as in High Q. */ +static int32_t filter_atten[16] = { + 65536, 61869, 57079, 53269, 49145, 44820, 40877, 34792, 32845, 30653, 28607, + 26392, 24630, 22463, 20487, 18470 +}; + + +static int32_t filt_coeffs[16][256][3]; + +#define READ16_SWITCH(addr, var) switch ((addr) & 2) \ { \ case 0: ret = (var) & 0xffff; break; \ case 2: ret = ((var) >> 16) & 0xffff; break; \ } -#define WRITE16(addr, var, val) switch ((addr) & 2) \ +#define WRITE16_SWITCH(addr, var, val) switch ((addr) & 2) \ { \ case 0: var = (var & 0xffff0000) | (val); break; \ case 2: var = (var & 0x0000ffff) | ((val) << 16); break; \ } -static __inline int16_t EMU8K_READ(emu8k_t *emu8k, uint16_t addr) +#ifdef EMU8K_DEBUG_REGISTERS +uint32_t dw_value = 0; +uint32_t last_read = 0; +uint32_t last_write = 0; +uint32_t rep_count_r = 0; +uint32_t rep_count_w = 0; + +# define READ16(addr, var) READ16_SWITCH(addr, var) \ + if ((addr) & 2) { \ + const char *name=0; \ + switch(addr) { \ + case 0x620: case 0x622: \ + name = PORT_NAMES[0][emu8k->cur_reg]; \ + break; \ + case 0xA20: \ + name = PORT_NAMES[1][emu8k->cur_reg]; \ + break; \ + case 0xA22: \ + name = PORT_NAMES[2][emu8k->cur_reg]; \ + break; \ + } \ + if (name == 0) { \ + /*pclog("EMU8K READ %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_voice,ret);*/ \ + } else { \ + /*pclog("EMU8K READ %s (%d): %04X\n",name,emu8k->cur_voice, ret);*/ \ + }\ + } +# define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) \ + if ((addr) & 2) { \ + const char *name=0; \ + switch(addr) { \ + case 0x620: case 0x622: \ + name = PORT_NAMES[0][emu8k->cur_reg]; \ + break; \ + case 0xA20: \ + name = PORT_NAMES[1][emu8k->cur_reg]; \ + break; \ + case 0xA22: \ + name = PORT_NAMES[2][emu8k->cur_reg]; \ + break; \ + } \ + if (name == 0) { \ + /*pclog("EMU8K WRITE %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_voice, val);*/ \ + } else { \ + pclog("EMU8K WRITE %s (%d): %04X\n",name,emu8k->cur_voice, val); \ + }\ + } + +#else +# define READ16(addr, var) READ16_SWITCH(addr, var) +# define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) +#endif /* EMU8K_DEBUG_REGISTERS */ + + +static inline int16_t EMU8K_READ(emu8k_t *emu8k, uint32_t addr) +{ + const register emu8k_mem_pointers_t addrmem = {{addr}}; + return emu8k->ram_pointers[addrmem.hb_address][addrmem.lw_address]; +} + +static inline int16_t EMU8K_READ_INTERP_LINEAR(emu8k_t *emu8k, uint32_t int_addr, uint16_t fract) +{ + /* The interpolation in AWE32 used a so-called patented 3-point interpolation + ( I guess some sort of spline having one point before and one point after). + Also, it has the consequence that the playback is delayed by one sample. + I simulate the "one sample later" than the address with addr+1 and addr+2 + instead of +0 and +1 */ + int16_t dat1 = EMU8K_READ(emu8k, int_addr+1); + int32_t dat2 = EMU8K_READ(emu8k, int_addr+2); + dat1 += ((dat2-(int32_t)dat1)* fract) >> 16; + return dat1; +} + +static inline int16_t EMU8K_READ_INTERP_CUBIC(emu8k_t *emu8k, uint32_t int_addr, uint16_t fract) +{ +/* if ((addr & EMU8K_FM_MEM_ADDRESS) == EMU8K_FM_MEM_ADDRESS) { */ + /* TODO: I still have to verify how this works, but I think that + the card could use two oscillators (usually 31 and 32) where it would + be writing the OPL3 output, and to which, chorus and reverb could be applied to get + those effects for OPL3 sounds. */ +/* } */ + + /* This is cubic interpolation. + Not the same than 3-point interpolation, but a better approximation than linear + interpolation. + Also, it takes into account the "Note that the actual audio location is the point + 1 word higher than this value due to interpolation offset". + That's why the pointers are 0, 1, 2, 3 and not -1, 0, 1, 2 */ + int32_t dat2 = EMU8K_READ(emu8k, int_addr+1); + if (fract) { + const int32_t *table = &cubic_table[fract>>(16-CUBIC_RESOLUTION_LOG)]; + const int32_t dat1 = EMU8K_READ(emu8k, int_addr); + const int32_t dat3 = EMU8K_READ(emu8k, int_addr+2); + const int32_t dat4 = EMU8K_READ(emu8k, int_addr+3); + /* 16bit*16bit and back to 16bit. (using >> 15 because the table is signed integer) + Warning: there exists the possibility of interger overflow. */ + dat2 = (int16_t)((dat1*table[0] + dat2*table[1] + dat3*table[2] + dat4*table[3]) >> 15); + } + return dat2; +} + +static inline void EMU8K_WRITE(emu8k_t *emu8k, uint32_t addr, uint16_t val) { addr &= EMU8K_MEM_ADDRESS_MASK; - /* TODO: I've read that the AWE64 Gold model had a 4MB Rom. It would be interesting - to find that rom and do some tests with it. */ - if (addr < EMU8K_ROM_MEM_1MB_END) - return emu8k->rom[addr]; - if (addr < EMU8K_RAM_MEM_START || addr >= emu8k->ram_end_addr) - return 0; - if (!emu8k->ram) - return 0; - return emu8k->ram[addr - EMU8K_RAM_MEM_START]; -} - -static __inline int16_t EMU8K_READ_INTERP(emu8k_t *emu8k, uint16_t addr) -{ - int16_t dat1 = EMU8K_READ(emu8k, addr >> 8); - int16_t dat2 = EMU8K_READ(emu8k, (addr >> 8) + 1); - return ((dat1 * (0xff - (addr & 0xff))) + (dat2 * (addr & 0xff))) >> 8; -} - -static __inline void EMU8K_WRITE(emu8k_t *emu8k, uint16_t addr, uint16_t val) -{ - if ( !emu8k->ram || addr < EMU8K_RAM_MEM_START) + if ( !emu8k->ram || addr < EMU8K_RAM_MEM_START || addr >= EMU8K_FM_MEM_ADDRESS ) return; - /* It looks like if an application writes to a memory part outside of the available amount on the card, - it wraps, and opencubicplayer uses that to detect the amount of memory, as opposed to simply check - at the address that it has just tried to write. */ - addr &= EMU8K_MEM_ADDRESS_MASK; + /* It looks like if an application writes to a memory part outside of the available + amount on the card, it wraps, and opencubicplayer uses that to detect the amount + of memory, as opposed to simply check at the address that it has just tried to write. */ while (addr >= emu8k->ram_end_addr) { addr -= emu8k->ram_end_addr - EMU8K_RAM_MEM_START; } emu8k->ram[addr - EMU8K_RAM_MEM_START] = val; } -static int ff = 0; - uint16_t emu8k_inw(uint16_t addr, void *p) { emu8k_t *emu8k = (emu8k_t *)p; uint16_t ret = 0xffff; -/* pclog("emu8k_inw %04X reg=%i voice=%i\n", addr, emu8k->cur_reg, emu8k->cur_voice);*/ - addr -= 0x220; - switch (addr & 0xc02) +#ifdef EMU8K_DEBUG_REGISTERS + if (addr == 0xE22) { + pclog("EMU8K READ POINTER: %d\n", + ((0x80 | ((random_helper + 1) & 0x1F)) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice); + } else if ((addr&0xF00) == 0x600) { + /* These are automatically reported by READ16 */ + } else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 0) { + /* These are automatically reported by READ16 */ + } else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 1) { + uint32_t tmpz = ((addr&0xF00) << 16)|(emu8k->cur_reg<<5); + if (tmpz != last_read) { + if (rep_count_r>1) { + pclog("EMU8K ...... for %d times\n", rep_count_r); + rep_count_r=0; + } + last_read=tmpz; + pclog("EMU8K READ RAM I/O or configuration or clock \n"); + } + } + else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { + uint32_t tmpz = ((addr&0xF00) << 16); + if (tmpz != last_read) { + if (rep_count_r>1) { + pclog("EMU8K ...... for %d times\n", rep_count_r); + rep_count_r=0; + } + last_read=tmpz; + pclog("EMU8K READ INIT \n"); + } + } + else { + uint32_t tmpz = (addr << 16)|(emu8k->cur_reg<<5)| emu8k->cur_voice; + if (tmpz != last_read) { + char* name = 0; + uint16_t val = 0xBAAD; + if (addr == 0xA20) { + name = PORT_NAMES[1][emu8k->cur_reg]; + switch (emu8k->cur_reg) + { + case 2: val = emu8k->init1[emu8k->cur_voice]; break; + case 3: val = emu8k->init3[emu8k->cur_voice]; break; + case 4: val = emu8k->voice[emu8k->cur_voice].envvol; break; + case 5: val = emu8k->voice[emu8k->cur_voice].dcysusv; break; + case 6: val = emu8k->voice[emu8k->cur_voice].envval; break; + case 7: val = emu8k->voice[emu8k->cur_voice].dcysus; break; + } + } + if (addr == 0xA22) { + name = PORT_NAMES[2][emu8k->cur_reg]; + switch (emu8k->cur_reg) + { + case 2: val = emu8k->init2[emu8k->cur_voice]; break; + case 3: val = emu8k->init4[emu8k->cur_voice]; break; + case 4: val = emu8k->voice[emu8k->cur_voice].atkhldv; break; + case 5: val = emu8k->voice[emu8k->cur_voice].lfo1val; break; + case 6: val = emu8k->voice[emu8k->cur_voice].atkhld; break; + case 7: val = emu8k->voice[emu8k->cur_voice].lfo2val; break; + } + } + if (addr == 0xE20) { + name = PORT_NAMES[3][emu8k->cur_reg]; + switch (emu8k->cur_reg) + { + case 0: val = emu8k->voice[emu8k->cur_voice].ip; break; + case 1: val = emu8k->voice[emu8k->cur_voice].ifatn; break; + case 2: val = emu8k->voice[emu8k->cur_voice].pefe; break; + case 3: val = emu8k->voice[emu8k->cur_voice].fmmod; break; + case 4: val = emu8k->voice[emu8k->cur_voice].tremfrq; break; + case 5: val = emu8k->voice[emu8k->cur_voice].fm2frq2;break; + case 6: val = 0xffff; break; + case 7: val = 0x1c | ((emu8k->id & 0x0002) ? 0xff02 : 0); break; + } + + } + if (rep_count_r>1) { + pclog("EMU8K ...... for %d times\n", rep_count_r); + } + if (name == 0) { + pclog("EMU8K READ %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice,val); + } + + rep_count_r=0; + last_read=tmpz; + } + rep_count_r++; + } +#endif /* EMU8K_DEBUG_REGISTERS */ + + + switch (addr & 0xF02) { - case 0x400: case 0x402: /*Data0*/ + case 0x600: case 0x602: /*Data0*/ /* also known as BLASTER+0x400 and EMU+0x000 */ switch (emu8k->cur_reg) { case 0: - { - uint32_t var = (emu8k->voice[emu8k->cur_voice].cpf & 0xFFFF0000) | ((emu8k->voice[emu8k->cur_voice].addr >> 16) & 0xFFFF); - READ16(addr, var); - return ret; - } + READ16(addr, emu8k->voice[emu8k->cur_voice].cpf); + return ret; case 1: READ16(addr, emu8k->voice[emu8k->cur_voice].ptrx); @@ -113,8 +477,13 @@ uint16_t emu8k_inw(uint16_t addr, void *p) READ16(addr, emu8k->voice[emu8k->cur_voice].vtft); return ret; - case 4: case 5: /*???*/ - return 0xffff; + case 4: + READ16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_4); + return ret; + + case 5: + READ16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_5); + return ret; case 6: READ16(addr, emu8k->voice[emu8k->cur_voice].psst); @@ -126,20 +495,30 @@ uint16_t emu8k_inw(uint16_t addr, void *p) } break; - case 0x800: /*Data1*/ + case 0xA00: /*Data1*/ /* also known as BLASTER+0x800 and EMU+0x400 */ switch (emu8k->cur_reg) { case 0: - { - emu8k->voice[emu8k->cur_voice].ccca = - (emu8k->voice[emu8k->cur_voice].ccca & 0xFF000000) | ((emu8k->voice[emu8k->cur_voice].addr >> 32) & EMU8K_MEM_ADDRESS_MASK); - READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); - return ret; - } + READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); + return ret; case 1: switch (emu8k->cur_voice) { + case 9: + READ16(addr, emu8k->hwcf4); + return ret; + case 10: + READ16(addr, emu8k->hwcf5); + return ret; + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ + case 13: + READ16(addr, emu8k->hwcf6); + return ret; + case 14: + READ16(addr, emu8k->hwcf7); + return ret; + case 20: READ16(addr, emu8k->smalr); return ret; @@ -157,10 +536,10 @@ uint16_t emu8k_inw(uint16_t addr, void *p) { uint16_t val = emu8k->smld_buffer; emu8k->smld_buffer = EMU8K_READ(emu8k, emu8k->smalr); -/* pclog("emu8k_SMLR in %04X (%04X) %08X\n", val, emu8k->smld_buffer, emu8k->smalr);*/ - emu8k->smalr++; + emu8k->smalr = (emu8k->smalr+1) & EMU8K_MEM_ADDRESS_MASK; return val; } + /*The EMU8000 PGM describes the return values of these registers as 'a VLSI error'*/ case 29: /*Configuration Word 1*/ return (emu8k->hwcf1 & 0xfe) | (emu8k->hwcf3 & 0x01); @@ -171,69 +550,108 @@ uint16_t emu8k_inw(uint16_t addr, void *p) } break; - case 2: /*INIT1*/ - case 3: /*INIT3*/ - return 0xffff; /*Can we read anything useful from here?*/ + case 2: + return emu8k->init1[emu8k->cur_voice]; + case 3: + return emu8k->init3[emu8k->cur_voice]; + + case 4: + return emu8k->voice[emu8k->cur_voice].envvol; + case 5: return emu8k->voice[emu8k->cur_voice].dcysusv; + + case 6: + return emu8k->voice[emu8k->cur_voice].envval; case 7: return emu8k->voice[emu8k->cur_voice].dcysus; } break; - case 0x802: /*Data2*/ + case 0xA02: /*Data2*/ /* also known as BLASTER+0x802 and EMU+0x402 */ switch (emu8k->cur_reg) { case 0: - { - READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); - return ret; - } + READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); + return ret; case 1: switch (emu8k->cur_voice) { + case 9: + READ16(addr, emu8k->hwcf4); + return ret; + case 10: + READ16(addr, emu8k->hwcf5); + return ret; + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ + case 13: + READ16(addr, emu8k->hwcf6); + return ret; + case 14: + READ16(addr, emu8k->hwcf7); + return ret; + + /* Simulating empty/full bits by unsetting it once read. */ case 20: - READ16(addr, emu8k->smalr | ff); - ff ^= 0x80000000; + READ16(addr, emu8k->smalr|dmareadbit); + /* xor with itself to set to zero faster. */ + dmareadbit^=dmareadbit; return ret; case 21: - READ16(addr, emu8k->smarr | ff); - ff ^= 0x80000000; + READ16(addr, emu8k->smarr|dmareadbit); + /* xor with itself to set to zero faster. */ + dmareadbit^=dmareadbit; return ret; case 22: - READ16(addr, emu8k->smalw); + READ16(addr, emu8k->smalw|dmawritebit); + /* xor with itself to set to zero faster. */ + dmawritebit^=dmawritebit; return ret; case 23: - READ16(addr, emu8k->smarw); + READ16(addr, emu8k->smarw|dmawritebit); + /* xor with itself to set to zero faster. */ + dmawritebit^=dmawritebit; return ret; case 26: { uint16_t val = emu8k->smrd_buffer; emu8k->smrd_buffer = EMU8K_READ(emu8k, emu8k->smarr); -/* pclog("emu8k_SMRR in %04X (%04X) %08X\n", val, emu8k->smrd_buffer, emu8k->smarr);*/ - emu8k->smarr++; + emu8k->smarr = (emu8k->smarr+1) & EMU8K_MEM_ADDRESS_MASK; return val; } - - case 27: /*Sample Counter*/ + /*TODO: We need to improve the precision of this clock, since + it is used by programs to wait. Not critical, but should help reduce + the amount of calls and wait time */ + case 27: /*Sample Counter ( 44Khz clock) */ return emu8k->wc; } break; - case 2: /*INIT2*/ - case 3: /*INIT4*/ - return 0xffff; /*Can we read anything useful from here?*/ + case 2: + return emu8k->init2[emu8k->cur_voice]; + + case 3: + return emu8k->init4[emu8k->cur_voice]; case 4: return emu8k->voice[emu8k->cur_voice].atkhldv; + + case 5: + return emu8k->voice[emu8k->cur_voice].lfo1val; + + case 6: + return emu8k->voice[emu8k->cur_voice].atkhld; + + case 7: + return emu8k->voice[emu8k->cur_voice].lfo2val; } break; - case 0xc00: /*Data3*/ + case 0xE00: /*Data3*/ /* also known as BLASTER+0xC00 and EMU+0x800 */ switch (emu8k->cur_reg) { case 0: @@ -261,34 +679,96 @@ uint16_t emu8k_inw(uint16_t addr, void *p) return 0x1c | ((emu8k->id & 0x0002) ? 0xff02 : 0); } break; - case 0xc02: + + case 0xE02: /* Pointer */ /* also known as BLASTER+0xC02 and EMU+0x802 */ /* LS five bits = channel number, next 3 bits = register number and MS 8 bits = VLSI test register. - Impulse tracker tests the non variability of the LS byte and the variability - of the MS byte to determine that it really is an AWE32. */ - return ((rand()&0xFF) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice; + Impulse tracker tests the non variability of the LS byte that it has set, and the variability + of the MS byte to determine that it really is an AWE32. + cubic player has a similar code, where it waits until value & 0x1000 is nonzero, and then waits again until it changes to zero. */ + random_helper = (random_helper + 1) & 0x1F; + return ((0x80 | random_helper) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice; } -/* fatal("Bad EMU8K inw from %08X\n", addr);*/ + pclog("EMU8K READ : Unknown register read: %04X-%02X(%d/%d) \n", addr, (emu8k->cur_reg << 5) | emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); return 0xffff; } void emu8k_outw(uint16_t addr, uint16_t val, void *p) { - float q; emu8k_t *emu8k = (emu8k_t *)p; + /* TODO: I would like to not call this here, but i found it was needed or else cubic player would not finish opening (take a looot more of time than usual). + Basically, being here means that the audio is generated in the emulation thread, instead of the audio thread. */ emu8k_update(emu8k); -/* pclog("emu8k_outw : addr=%08X reg=%i voice=%i val=%04X\n", addr, emu8k->cur_reg, emu8k->cur_voice, val);*/ - addr -= 0x220; - switch (addr & 0xc02) + +#ifdef EMU8K_DEBUG_REGISTERS + if (addr == 0xE22) { + /* pclog("EMU8K WRITE POINTER: %d\n", val); */ + } else if ((addr&0xF00) == 0x600) { + /* These are automatically reported by WRITE16 */ + } else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 0) { + /* These are automatically reported by WRITE16 */ + } else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 1) { + uint32_t tmpz = ((addr&0xF00) << 16)|(emu8k->cur_reg<<5); + if (tmpz != last_write) { + if (rep_count_w>1) { + pclog("EMU8K ...... for %d times\n", rep_count_w); + rep_count_w=0; + } + last_write=tmpz; + pclog("EMU8K WRITE RAM I/O or configuration \n"); + } + } + else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { + uint32_t tmpz = ((addr&0xF00) << 16); + if (tmpz != last_write) { + if (rep_count_w>1) { + pclog("EMU8K ...... for %d times\n", rep_count_w); + rep_count_w=0; + } + last_write=tmpz; + pclog("EMU8K WRITE INIT \n"); + } + } + else if (addr != 0xE22) { + uint32_t tmpz = (addr << 16)|(emu8k->cur_reg<<5)| emu8k->cur_voice; + if (tmpz != last_write) { + char* name = 0; + if (addr == 0xA20) { + name = PORT_NAMES[1][emu8k->cur_reg]; + } + else if (addr == 0xA22) { + name = PORT_NAMES[2][emu8k->cur_reg]; + } + else if (addr == 0xE20) { + name = PORT_NAMES[3][emu8k->cur_reg]; + } + + if (rep_count_w>1) { + pclog("EMU8K ...... for %d times\n", rep_count_w); + } + if (name == 0) { + pclog("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); + } else { + pclog("EMU8K WRITE %s (%d): %04X\n",name,emu8k->cur_voice, val); \ + } + + rep_count_w=0; + last_write=tmpz; + } + rep_count_w++; + } +#endif /* EMU8K_DEBUG_REGISTERS */ + + + switch (addr & 0xF02) { - case 0x400: case 0x402: /*Data0*/ + case 0x600: case 0x602: /*Data0*/ switch (emu8k->cur_reg) { case 0: WRITE16(addr, emu8k->voice[emu8k->cur_voice].cpf, val); - /* Ignoring any effect over writing to the "fractional address". The docs says that this value is constantly - updating, so it has no actual effect. */ + /* The docs says that this value is constantly updating, and it should have no actual effect. Actions should be done over ptrx */ return; case 1: @@ -297,46 +777,69 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) case 2: WRITE16(addr, emu8k->voice[emu8k->cur_voice].cvcf, val); + /* The docs says that this value is constantly updating, and it should have no actual effect. Actions should be done over vtft */ return; case 3: WRITE16(addr, emu8k->voice[emu8k->cur_voice].vtft, val); return; + case 4: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_4, val); + return; + + case 5: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_5, val); + return; + case 6: - WRITE16(addr, emu8k->voice[emu8k->cur_voice].psst, val); - /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ - emu8k->voice[emu8k->cur_voice].loop_start = (uint64_t)(emu8k->voice[emu8k->cur_voice].psst & EMU8K_MEM_ADDRESS_MASK) << 32; - if (addr & 2) { - emu8k->voice[emu8k->cur_voice].vol_l = val >> 8; - emu8k->voice[emu8k->cur_voice].vol_r = 255 - (val >> 8); + emu8k_voice_t *emu_voice = &emu8k->voice[emu8k->cur_voice]; + WRITE16(addr, emu_voice->psst, val); + /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ + emu_voice->loop_start.int_address = emu_voice->psst & EMU8K_MEM_ADDRESS_MASK; + if (addr & 2) + { + emu_voice->vol_l = emu_voice->psst_pan; + emu_voice->vol_r = 255 - (emu_voice->psst_pan); + } } -/* pclog("emu8k_outl : write PSST %08X l %i r %i\n", emu8k->voice[emu8k->cur_voice].psst, emu8k->voice[emu8k->cur_voice].vol_l, emu8k->voice[emu8k->cur_voice].vol_r);*/ return; case 7: WRITE16(addr, emu8k->voice[emu8k->cur_voice].csl, val); /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ - emu8k->voice[emu8k->cur_voice].loop_end = (uint64_t)(emu8k->voice[emu8k->cur_voice].csl & EMU8K_MEM_ADDRESS_MASK) << 32; -/* pclog("emu8k_outl : write CSL %08X\n", emu8k->voice[emu8k->cur_voice].csl);*/ + emu8k->voice[emu8k->cur_voice].loop_end.int_address = emu8k->voice[emu8k->cur_voice].csl & EMU8K_MEM_ADDRESS_MASK; return; } break; - case 0x800: /*Data1*/ + case 0xA00: /*Data1*/ switch (emu8k->cur_reg) { case 0: WRITE16(addr, emu8k->voice[emu8k->cur_voice].ccca, val); /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ - emu8k->voice[emu8k->cur_voice].addr = (uint64_t)(emu8k->voice[emu8k->cur_voice].ccca & EMU8K_MEM_ADDRESS_MASK) << 32; -/* pclog("emu8k_outl : write CCCA %08X\n", emu8k->voice[emu8k->cur_voice].ccca);*/ + emu8k->voice[emu8k->cur_voice].addr.int_address = emu8k->voice[emu8k->cur_voice].ccca & EMU8K_MEM_ADDRESS_MASK; return; case 1: switch (emu8k->cur_voice) { + case 9: + WRITE16(addr, emu8k->hwcf4, val); + return; + case 10: + WRITE16(addr, emu8k->hwcf5, val); + return; + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ + case 13: + WRITE16(addr, emu8k->hwcf6, val); + return; + case 14: + WRITE16(addr, emu8k->hwcf7, val); + return; + case 20: WRITE16(addr, emu8k->smalr, val); return; @@ -352,149 +855,361 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) case 26: EMU8K_WRITE(emu8k, emu8k->smalw, val); -/* pclog("emu8k_SMLW %04X %08X\n", val, emu8k->smalw);*/ -/* if (val = 0xffff && emu8k->smalw == 0x200000) - output = 3;*/ - emu8k->smalw++; - break; + emu8k->smalw = (emu8k->smalw+1) & EMU8K_MEM_ADDRESS_MASK; + return; - case 29: /*Configuration Word 1*/ + case 29: emu8k->hwcf1 = val; return; - case 30: /*Configuration Word 2*/ + case 30: emu8k->hwcf2 = val; return; - case 31: /*Configuration Word 3*/ + case 31: emu8k->hwcf3 = val; return; } break; - case 5: -/* pclog("emu8k_outw : write DCYSUSV %04X\n", val);*/ - emu8k->voice[emu8k->cur_voice].dcysusv = val; - emu8k->voice[emu8k->cur_voice].env_sustain = (((val >> 8) & 0x7f) << 5) << 9; - if (val & 0x8000) /*Release*/ - { - emu8k->voice[emu8k->cur_voice].env_state = ENV_RELEASE; - emu8k->voice[emu8k->cur_voice].env_release = val & 0x7f; - } - else /*Decay*/ - emu8k->voice[emu8k->cur_voice].env_decay = val & 0x7f; - if (val & 0x80) - emu8k->voice[emu8k->cur_voice].env_state = ENV_STOPPED; + /* TODO: Read Reverb, Chorus and equalizer setups */ + case 2: + emu8k->init1[emu8k->cur_voice] = val; return; - case 7: -/* pclog("emu8k_outw : write DCYSUS %04X\n", val);*/ - emu8k->voice[emu8k->cur_voice].dcysus = val; - emu8k->voice[emu8k->cur_voice].menv_sustain = (((val >> 8) & 0x7f) << 5) << 9; - if (val & 0x8000) /*Release*/ - { - emu8k->voice[emu8k->cur_voice].menv_state = ENV_RELEASE; - emu8k->voice[emu8k->cur_voice].menv_release = val & 0x7f; + case 3: + emu8k->init3[emu8k->cur_voice] = val; + if (emu8k->init1[0] != 0x03FF) { + /* If not in initialization, configure chorus */ + if (emu8k->cur_voice == 9) { + emu8k->chorus_engine.feedback = (val&0xFF); + } + else if (emu8k->cur_voice == 12) { + emu8k->chorus_engine.delay_samples_central = val; + } + } + return; + + case 4: + emu8k->voice[emu8k->cur_voice].envvol = val; + emu8k->voice[emu8k->cur_voice].vol_envelope.delay_samples = ENVVOL_TO_EMU_SAMPLES(val); + return; + + case 5: + { + emu8k->voice[emu8k->cur_voice].dcysusv = val; + emu8k_envelope_t * const vol_env = &emu8k->voice[emu8k->cur_voice].vol_envelope; + emu8k->voice[emu8k->cur_voice].env_engine_on = DCYSUSV_GENERATOR_ENGINE_ON(val); + + /* Converting the input in dBs to envelope value range. */ + vol_env->sustain_value_db_oct = DCYSUSV_SUS_TO_ENV_RANGE(DCYSUSV_SUSVALUE_GET(val)); + vol_env->ramp_amount_db_oct = env_decay_to_dbs_or_oct[DCYSUSV_DECAYRELEASE_GET(val)]; + if (DCYSUSV_IS_RELEASE(val)) + { + if (vol_env->state == ENV_DELAY || vol_env->state == ENV_ATTACK || vol_env->state == ENV_HOLD) { + vol_env->value_db_oct = env_vol_amplitude_to_db[vol_env->value_amp_hz >> 5] << 5; + if (vol_env->value_db_oct > (1 << 21)) { + vol_env->value_db_oct = 1 << 21; + } + } + + vol_env->state = (vol_env->value_db_oct >= vol_env->sustain_value_db_oct) ? ENV_RAMP_DOWN : ENV_RAMP_UP; + } + } + return; + + case 6: + emu8k->voice[emu8k->cur_voice].envval = val; + emu8k->voice[emu8k->cur_voice].mod_envelope.delay_samples = ENVVAL_TO_EMU_SAMPLES(val); + return; + + case 7: + { + emu8k->voice[emu8k->cur_voice].dcysus = val; + emu8k_envelope_t* const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; + mod_env->sustain_value_db_oct = DCYSUS_SUS_TO_ENV_RANGE(DCYSUS_SUSVALUE_GET(val)); + mod_env->ramp_amount_db_oct = env_decay_to_dbs_or_oct[DCYSUS_DECAYRELEASE_GET(val)]; + if (DCYSUS_IS_RELEASE(val)) + { + if (mod_env->state == ENV_DELAY || mod_env->state == ENV_ATTACK || mod_env->state == ENV_HOLD) { + mod_env->value_db_oct = env_mod_hertz_to_octave[mod_env->value_amp_hz >> 9] << 9; + if (mod_env->value_db_oct >= (1 << 21)) { + mod_env->value_db_oct = (1 << 21)-1; + } + } + + mod_env->state = (mod_env->value_db_oct >= mod_env->sustain_value_db_oct) ? ENV_RAMP_DOWN : ENV_RAMP_UP; + } } - else /*Decay*/ - emu8k->voice[emu8k->cur_voice].menv_decay = val & 0x7f; - if (val & 0x80) - emu8k->voice[emu8k->cur_voice].menv_state = ENV_STOPPED; return; } break; - case 0x802: /*Data2*/ + case 0xA02: /*Data2*/ switch (emu8k->cur_reg) { case 0: { - WRITE16(addr, emu8k->voice[emu8k->cur_voice].ccca, val); - emu8k->voice[emu8k->cur_voice].addr = (uint64_t)(emu8k->voice[emu8k->cur_voice].ccca & EMU8K_MEM_ADDRESS_MASK) << 32; - /* TODO: Since "fractional address" is a separate register (cpf), should we add its contents to .addr or we assume that it - is reset to zero? */ - - q = (float)(emu8k->voice[emu8k->cur_voice].ccca >> 28) / 15.0f; - q /= 10.0f; /*Horrible and wrong hack*/ - emu8k->voice[emu8k->cur_voice].q = (int32_t)((1.0f / (0.707f + q)) * 256.0f); - -/* pclog("emu8k_outl : write CCCA %08X Q %f invQ %X\n", emu8k->voice[emu8k->cur_voice].ccca, q, emu8k->voice[emu8k->cur_voice].q);*/ + emu8k_voice_t *emu_voice = &emu8k->voice[emu8k->cur_voice]; + WRITE16(addr, emu_voice->ccca, val); + emu_voice->addr.int_address = emu_voice->ccca & EMU8K_MEM_ADDRESS_MASK; + uint32_t paramq = CCCA_FILTQ_GET(emu_voice->ccca); + emu_voice->filt_att = filter_atten[paramq]; + emu_voice->filterq_idx = paramq; } return; case 1: switch (emu8k->cur_voice) { - case 20: - WRITE16(addr, emu8k->smalr, val); + case 9: + WRITE16(addr, emu8k->hwcf4, val); + emu8k->chorus_engine.delay_offset_samples_right.addr = emu8k->hwcf4<<24; /* (1/256th of a 44Khz sample) */ return; - case 21: - WRITE16(addr, emu8k->smarr, val); + case 10: + { + WRITE16(addr, emu8k->hwcf5, val); + /* The scale of this value is unknown. I've taken it as milliHz. + Another interpretation could be periods. (and so, Hz = 1/period) */ + double osc_speed = emu8k->hwcf5; +#if 1 /* milliHz */ + /* milliHz to lfotable samples. */ + osc_speed *= 65.536/44100.0; +#elif 0 /* periods */ + osc_speed = 1.0/osc_speed; + /* Hz to lfotable samples. */ + osc_speed *= 65536/44100.0; +#endif + /* left shift 32bits for 32.32 fixed.point */ + osc_speed *= 65536.0*65536.0; + emu8k->chorus_engine.lfo_inc.addr = (uint64_t)osc_speed; + } return; - case 22: - WRITE16(addr, emu8k->smalw, val); + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ + case 13: + WRITE16(addr, emu8k->hwcf6, val); return; - case 23: - WRITE16(addr, emu8k->smarw, val); + case 14: + WRITE16(addr, emu8k->hwcf7, val); + return; + + case 20: /* Top 8 bits are for Empty (MT) bit or non-addressable. */ + WRITE16(addr, emu8k->smalr, val&0xFF); + dmareadbit=0x8000; + return; + case 21: /* Top 8 bits are for Empty (MT) bit or non-addressable. */ + WRITE16(addr, emu8k->smarr, val&0xFF); + dmareadbit=0x8000; + return; + case 22: /* Top 8 bits are for full bit or non-addressable. */ + WRITE16(addr, emu8k->smalw, val&0xFF); + return; + case 23: /* Top 8 bits are for full bit or non-addressable. */ + WRITE16(addr, emu8k->smarw, val&0xFF); return; case 26: + dmawritebit=0x8000; EMU8K_WRITE(emu8k, emu8k->smarw, val); -/* pclog("emu8k_SMRW %04X %08X\n", val, emu8k->smarw);*/ emu8k->smarw++; - break; + return; } break; + /* TODO: Read Reverb, Chorus and equalizer setups */ + case 2: + emu8k->init2[emu8k->cur_voice] = val; + return; + case 3: + emu8k->init4[emu8k->cur_voice] = val; + if (emu8k->init1[0] != 0x03FF) { + /* If not in initialization, configure chorus */ + if (emu8k->cur_voice == 3) { + emu8k->chorus_engine.lfodepth_samples = ((val&0xFF)*emu8k->chorus_engine.delay_samples_central) >> 8; + } + } + return ; + case 4: -/* pclog("emu8k_outw : write ATKHLDV %04X\n", val);*/ - emu8k->voice[emu8k->cur_voice].atkhldv = val; - emu8k->voice[emu8k->cur_voice].env_attack = (val & 0x7f) << 6; - if (!(val & 0x8000)) /*Trigger attack*/ - emu8k->voice[emu8k->cur_voice].env_state = ENV_ATTACK; + { + emu8k->voice[emu8k->cur_voice].atkhldv = val; + emu8k_envelope_t* const vol_env = &emu8k->voice[emu8k->cur_voice].vol_envelope; + vol_env->attack_samples = env_attack_to_samples[ATKHLDV_ATTACK(val)]; + if (vol_env->attack_samples == 0) { + /* Eternal Mute? */ + vol_env->attack_amount_amp_hz = 0; + } + else { + /* Linear amplitude increase each sample. */ + vol_env->attack_amount_amp_hz = (1<<21) / vol_env->attack_samples; + } + vol_env->hold_samples = ATKHLDV_HOLD_TO_EMU_SAMPLES(val); + if (ATKHLDV_TRIGGER(val)) + { + /* TODO: I assume that "envelope trigger" is the same as new note + (since changing the IP can be done when modulating pitch too) */ + emu8k->voice[emu8k->cur_voice].lfo1_count.addr = 0; + emu8k->voice[emu8k->cur_voice].lfo2_count.addr = 0; + + vol_env->value_amp_hz = 0; + if (vol_env->delay_samples) + { + vol_env->state = ENV_DELAY; + } + else if (vol_env->attack_amount_amp_hz == 0) + { + vol_env->state = ENV_STOPPED; + } + else + { + vol_env->state = ENV_ATTACK; + /* TODO: Verify if "never attack" means eternal mute, + * or it means skip attack, go to hold". + if (vol_env->attack_amount == 0) + { + vol_env->value = (1 << 21); + vol_env->state = ENV_HOLD; + }*/ + } + } + } + return; + + case 5: + emu8k->voice[emu8k->cur_voice].lfo1val = val; + /* TODO: verify if this is set once, or set every time. */ + emu8k->voice[emu8k->cur_voice].lfo1_delay_samples = LFOxVAL_TO_EMU_SAMPLES(val); return; case 6: -/* pclog("emu8k_outw : write ATKHLD %04X\n", val);*/ - emu8k->voice[emu8k->cur_voice].atkhld = val; - emu8k->voice[emu8k->cur_voice].menv_attack = (val & 0x7f) << 6; - if (!(val & 0x8000)) /*Trigger attack*/ - emu8k->voice[emu8k->cur_voice].menv_state = ENV_ATTACK; + { + emu8k->voice[emu8k->cur_voice].atkhld = val; + emu8k_envelope_t* const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; + mod_env->attack_samples = env_attack_to_samples[ATKHLD_ATTACK(val)]; + if (mod_env->attack_samples == 0) { + /* Eternal Mute? */ + mod_env->attack_amount_amp_hz = 0; + } + else { + /* Linear amplitude increase each sample. */ + mod_env->attack_amount_amp_hz = (1<<21) / mod_env->attack_samples; + } + mod_env->hold_samples = ATKHLD_HOLD_TO_EMU_SAMPLES(val); + if (ATKHLD_TRIGGER(val)) + { + mod_env->value_amp_hz = 0; + mod_env->value_db_oct = 0; + if (mod_env->delay_samples) + { + mod_env->state = ENV_DELAY; + } + else if (mod_env->attack_amount_amp_hz == 0) + { + mod_env->state = ENV_STOPPED; + } + else + { + mod_env->state = ENV_ATTACK; + /* TODO: Verify if "never attack" means eternal start, + * or it means skip attack, go to hold". + if (mod_env->attack_amount == 0) + { + mod_env->value = (1 << 21); + mod_env->state = ENV_HOLD; + }*/ + } + } + } + return; + + case 7: + emu8k->voice[emu8k->cur_voice].lfo2val = val; + emu8k->voice[emu8k->cur_voice].lfo2_delay_samples = LFOxVAL_TO_EMU_SAMPLES(val); + return; } break; - case 0xc00: /*Data3*/ + case 0xE00: /*Data3*/ switch (emu8k->cur_reg) { case 0: emu8k->voice[emu8k->cur_voice].ip = val; - emu8k->voice[emu8k->cur_voice].pitch = val; + emu8k->voice[emu8k->cur_voice].ptrx_pit_target = freqtable[val] >> 18; return; case 1: - emu8k->voice[emu8k->cur_voice].ifatn = val; - emu8k->voice[emu8k->cur_voice].attenuation = attentable[val & 0xff]; - emu8k->voice[emu8k->cur_voice].cutoff = (val >> 8); -/* pclog("Attenuation now %02X %i\n", val & 0xff, emu8k->voice[emu8k->cur_voice].attenuation);*/ + { + emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->ifatn = val; + the_voice->initial_att = (((int32_t)the_voice->ifatn_attenuation <<21)/0xFF); + the_voice->vtft_vol_target = attentable[the_voice->ifatn_attenuation]; + + the_voice->initial_filter = (((int32_t)the_voice->ifatn_init_filter <<21)/0xFF); + if (the_voice->ifatn_init_filter==0xFF) { + the_voice->vtft_filter_target = 0xFFFF; + } else { + the_voice->vtft_filter_target = the_voice->initial_filter >> 5; + } + } return; case 2: - emu8k->voice[emu8k->cur_voice].pefe = val; - emu8k->voice[emu8k->cur_voice].fe_height = (int8_t)(val & 0xff); + { + emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->pefe = val; + if (the_voice->pefe_modenv_filter_height < 0) { + the_voice->fixed_modenv_filter_height = the_voice->pefe_modenv_filter_height*0x4000/0x80; + } else { + the_voice->fixed_modenv_filter_height = the_voice->pefe_modenv_filter_height*0x4000/0x7F; + } + if (the_voice->pefe_modenv_pitch_height < 0) { + the_voice->fixed_modenv_pitch_height = the_voice->pefe_modenv_pitch_height*0x4000/0x80; + } else { + the_voice->fixed_modenv_pitch_height = the_voice->pefe_modenv_pitch_height*0x4000/0x7F; + } + } return; case 3: - emu8k->voice[emu8k->cur_voice].fmmod = val; - emu8k->voice[emu8k->cur_voice].lfo1_fmmod = (val >> 8); + { + emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->fmmod = val; + if (the_voice->fmmod_lfo1_filt_mod < 0) { + the_voice->fixed_lfo1_filt_mod = the_voice->fmmod_lfo1_filt_mod*0x4000/0x80; + } else { + the_voice->fixed_lfo1_filt_mod = the_voice->fmmod_lfo1_filt_mod*0x4000/0x7F; + } + if (the_voice->fmmod_lfo1_vibrato < 0) { + the_voice->fixed_lfo1_vibrato = the_voice->fmmod_lfo1_vibrato*0x4000/0x80; + } else { + the_voice->fixed_lfo1_vibrato = the_voice->fmmod_lfo1_vibrato*0x4000/0x7F; + } + } return; case 4: - emu8k->voice[emu8k->cur_voice].tremfrq = val; - emu8k->voice[emu8k->cur_voice].lfo1_trem = (val >> 8); + { + emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->tremfrq = val; + the_voice->lfo1_speed = lfofreqtospeed[the_voice->tremfrq_lfo1_freq]; + if (the_voice->tremfrq_lfo1_tremolo < 0) { + the_voice->fixed_lfo1_tremolo = the_voice->tremfrq_lfo1_tremolo*0x4000/0x80; + } else { + the_voice->fixed_lfo1_tremolo = the_voice->tremfrq_lfo1_tremolo*0x4000/0x7F; + } + } return; case 5: - emu8k->voice[emu8k->cur_voice].fm2frq2 = val; - emu8k->voice[emu8k->cur_voice].lfo2_fmmod = (val >> 8); + { + emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->fm2frq2 = val; + the_voice->lfo2_speed = lfofreqtospeed[the_voice->fm2frq2_lfo2_freq]; + if (the_voice->fm2frq2_lfo2_vibrato < 0) { + the_voice->fixed_lfo2_vibrato = the_voice->fm2frq2_lfo2_vibrato*0x4000/0x80; + } else { + the_voice->fixed_lfo2_vibrato = the_voice->fm2frq2_lfo2_vibrato*0x4000/0x7F; + } + } return; case 7: /*ID?*/ @@ -503,15 +1218,19 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) } break; - case 0xc02: /*Pointer*/ + case 0xE02: /*Pointer*/ emu8k->cur_voice = (val & 31); emu8k->cur_reg = ((val >> 5) & 7); return; } + pclog("EMU8K WRITE: Unknown register write: %04X-%02X(%d/%d): %04X \n", addr, (emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg,emu8k->cur_voice, val); + } uint8_t emu8k_inb(uint16_t addr, void *p) { + /* Reading a single byte is a feature that at least Impulse tracker uses, + but only on detection code and not for odd addresses. */ if (addr & 1) return emu8k_inw(addr & ~1, p) >> 1; return emu8k_inw(addr, p) & 0xff; @@ -519,259 +1238,704 @@ uint8_t emu8k_inb(uint16_t addr, void *p) void emu8k_outb(uint16_t addr, uint8_t val, void *p) { + /* FIXME: AWE32 docs says that you cannot write in bytes, but if + an app were to use this, the content of the LSByte would be lost. */ if (addr & 1) emu8k_outw(addr & ~1, val << 8, p); else emu8k_outw(addr, val, p); } -void emu8k_update(emu8k_t *emu8k) +void emu8k_work_chorus(int32_t *inbuf, int32_t *outbuf, emu8k_chorus_eng_t *engine, int count) { - int32_t *buf; - int pos; - int c; - - int new_pos = (sound_pos_global * 44100) / 48000; - if (emu8k->pos < new_pos) + int pos; + for (pos = 0; pos < count; pos++) { + if (*inbuf != 0 ) { + pclog("chorus: bufferin pos:%d val:%d\n", pos, *inbuf); + } - buf = &emu8k->buffer[emu8k->pos*2]; - - for (pos = emu8k->pos; pos < new_pos; pos++) - emu8k->buffer[pos*2] = emu8k->buffer[pos*2 + 1] = 0; + + /* TODO: linear interpolate if the quality is not good enough. */ + int32_t offset_lfo = (lfotable[engine->lfo_pos.int_address] * engine->lfodepth_samples) >> 16; + int32_t fraction_part = (lfotable[engine->lfo_pos.int_address] * engine->lfodepth_samples) & 0xFFFF; - for (c = 0; c < 32; c++) - { - buf = &emu8k->buffer[emu8k->pos*2]; - - for (pos = emu8k->pos; pos < new_pos; pos++) - { - int32_t voice_l, voice_r; - int32_t dat; - int lfo1_vibrato, lfo2_vibrato; - - if (freqtable[emu8k->voice[c].pitch] >> 32) - dat = EMU8K_READ(emu8k, emu8k->voice[c].addr >> 32); - else - dat = EMU8K_READ_INTERP(emu8k, emu8k->voice[c].addr >> 24); + /* Work left */ + int32_t read = engine->write - engine->delay_samples_central - offset_lfo; + int next_value = read + 1; + if(read < 0) { + read += SOUNDBUFLEN; + if(next_value < 0) next_value += SOUNDBUFLEN; + } + else if(next_value >= SOUNDBUFLEN) { + next_value -= SOUNDBUFLEN; + if(read >= SOUNDBUFLEN) read -= SOUNDBUFLEN; + } + int32_t dat1 = engine->chorus_left_buffer[read]; + int32_t dat2 = engine->chorus_left_buffer[next_value]; + dat1 += ((dat2-(int32_t)dat1)* fraction_part) >> 16; + + engine->chorus_left_buffer[engine->write] = *inbuf + ((dat1 * engine->feedback)>>8); + + + /* Work right */ + read = engine->write - engine->delay_samples_central - engine->delay_offset_samples_right.int_address + offset_lfo; + if (fraction_partdelay_offset_samples_right.fract_address) { + fraction_part+=0x10000 - engine->delay_offset_samples_right.fract_address; + read--; + } else { + fraction_part -= engine->delay_offset_samples_right.fract_address; + } + + next_value = read + 1; + if(read < 0) { + read += SOUNDBUFLEN; + if(next_value < 0) next_value += SOUNDBUFLEN; + } + else if(next_value >= SOUNDBUFLEN) { + next_value -= SOUNDBUFLEN; + if(read >= SOUNDBUFLEN) read -= SOUNDBUFLEN; + } + int32_t dat3 = engine->chorus_right_buffer[read]; + int32_t dat4 = engine->chorus_right_buffer[next_value]; + dat3 += ((dat4-(int32_t)dat3)* fraction_part) >> 16; + + engine->chorus_right_buffer[engine->write] = *inbuf + ((dat3 * engine->feedback)>>8); + + ++engine->write; + engine->write %= SOUNDBUFLEN; + engine->lfo_pos.addr +=engine->lfo_inc.addr; + engine->lfo_pos.int_address %= SOUNDBUFLEN; - dat = (dat * emu8k->voice[c].attenuation) >> 16; - - dat = (dat * envtable[emu8k->voice[c].env_vol >> 9]) >> 16; - - if ((emu8k->voice[c].ccca >> 28) || (emu8k->voice[c].cutoff != 0xff)) - { - int cutoff = emu8k->voice[c].cutoff + ((emu8k->voice[c].menv_vol * emu8k->voice[c].fe_height) >> 20); - if (cutoff < 0) - cutoff = 0; - if (cutoff > 255) - cutoff = 255; - - emu8k->voice[c].vhp = ((-emu8k->voice[c].vbp * emu8k->voice[c].q) >> 8) - emu8k->voice[c].vlp - dat; - emu8k->voice[c].vlp += (emu8k->voice[c].vbp * filt_w0[cutoff]) >> 8; - emu8k->voice[c].vbp += (emu8k->voice[c].vhp * filt_w0[cutoff]) >> 8; - if (emu8k->voice[c].vlp < -32767) - dat = -32767; - else if (emu8k->voice[c].vlp > 32767) - dat = 32767; - else - dat = (int16_t)emu8k->voice[c].vlp; - } - - voice_l = (dat * emu8k->voice[c].vol_l) >> 7; - voice_r = (dat * emu8k->voice[c].vol_r) >> 7; - - (*buf++) += voice_l * 8192; - (*buf++) += voice_r * 8192; - - switch (emu8k->voice[c].env_state) - { - case ENV_ATTACK: - emu8k->voice[c].env_vol += emu8k->voice[c].env_attack; - emu8k->voice[c].vtft |= 0xffff0000; - if (emu8k->voice[c].env_vol >= (1 << 21)) - { - emu8k->voice[c].env_vol = 1 << 21; - emu8k->voice[c].env_state = ENV_DECAY; - } - break; - - case ENV_DECAY: - emu8k->voice[c].env_vol -= emu8k->voice[c].env_decay; - emu8k->voice[c].vtft = (emu8k->voice[c].vtft & ~0xffff0000) | ((emu8k->voice[c].env_sustain >> 5) << 16); - if (emu8k->voice[c].env_vol <= emu8k->voice[c].env_sustain) - { - emu8k->voice[c].env_vol = emu8k->voice[c].env_sustain; - emu8k->voice[c].env_state = ENV_SUSTAIN; - } - break; - - case ENV_RELEASE: - emu8k->voice[c].env_vol -= emu8k->voice[c].env_release; - emu8k->voice[c].vtft &= ~0xffff0000; - if (emu8k->voice[c].env_vol <= 0) - { - emu8k->voice[c].env_vol = 0; - emu8k->voice[c].env_state = ENV_STOPPED; - } - break; - } - - if (emu8k->voice[c].env_vol >= (1 << 21)) - emu8k->voice[c].cvcf &= ~0xffff0000; - else - emu8k->voice[c].cvcf = (emu8k->voice[c].cvcf & ~0xffff0000) | ((emu8k->voice[c].env_vol >> 5) << 16); - - switch (emu8k->voice[c].menv_state) - { - case ENV_ATTACK: - emu8k->voice[c].menv_vol += emu8k->voice[c].menv_attack; - if (emu8k->voice[c].menv_vol >= (1 << 21)) - { - emu8k->voice[c].menv_vol = 1 << 21; - emu8k->voice[c].menv_state = ENV_DECAY; - } - break; - - case ENV_DECAY: - emu8k->voice[c].menv_vol -= emu8k->voice[c].menv_decay; - if (emu8k->voice[c].menv_vol <= emu8k->voice[c].menv_sustain) - { - emu8k->voice[c].menv_vol = emu8k->voice[c].menv_sustain; - emu8k->voice[c].menv_state = ENV_SUSTAIN; - } - break; - - case ENV_RELEASE: - emu8k->voice[c].menv_vol -= emu8k->voice[c].menv_release; - if (emu8k->voice[c].menv_vol <= 0) - { - emu8k->voice[c].menv_vol = 0; - emu8k->voice[c].menv_state = ENV_STOPPED; - } - break; - } - - lfo1_vibrato = (lfotable[(emu8k->voice[c].lfo1_count >> 8) & 4095] * emu8k->voice[c].lfo1_fmmod) >> 9; - lfo2_vibrato = (lfotable[(emu8k->voice[c].lfo2_count >> 8) & 4095] * emu8k->voice[c].lfo2_fmmod) >> 9; - - emu8k->voice[c].addr += freqtable[(emu8k->voice[c].pitch + lfo1_vibrato + lfo2_vibrato) & 0xffff]; - if (emu8k->voice[c].addr >= emu8k->voice[c].loop_end) - emu8k->voice[c].addr -= (emu8k->voice[c].loop_end - emu8k->voice[c].loop_start); - - emu8k->voice[c].lfo1_count += (emu8k->voice[c].tremfrq & 0xff); - emu8k->voice[c].lfo2_count += (emu8k->voice[c].fm2frq2 & 0xff); - } - } - - buf = &emu8k->buffer[emu8k->pos*2]; - - for (pos = emu8k->pos; pos < new_pos; pos++) - { - buf[0] >>= 15; - buf[1] >>= 15; - - if (buf[0] < -32768) - buf[0] = -32768; - else if (buf[0] > 32767) - buf[0] = 32767; - - if (buf[1] < -32768) - buf[1] = -32768; - else if (buf[1] > 32767) - buf[1] = 32767; - - buf += 2; - } - - emu8k->wc += (new_pos - emu8k->pos); - - emu8k->pos = new_pos; + (*outbuf++) += dat1; + (*outbuf++) += dat3; + inbuf++; } } +void emu8k_work_reverb(emu8k_t *emu8k, int new_pos) +{ + /* TODO: Work reverb and add into buf */ +} +void emu8k_work_eq(emu8k_t *emu8k, int new_pos) +{ + /* TODO: Work EQ over buf */ +} + + +void emu8k_update(emu8k_t *emu8k) +{ + int new_pos = (sound_pos_global * 44100) / 48000; + if (emu8k->pos >= new_pos) + return; + + int32_t *buf; + emu8k_voice_t* emu_voice; + int pos; + int c; + + /* Clean the buffer since we will accumulate into it. */ + buf = &emu8k->buffer[emu8k->pos*2]; + memset(buf, 0, 2*(new_pos-emu8k->pos)*sizeof(emu8k->buffer[0])); + memset(&emu8k->chorus_in_buffer[emu8k->pos], 0, (new_pos-emu8k->pos)*sizeof(emu8k->chorus_in_buffer[0])); + + /* Voices section */ + for (c = 0; c < 32; c++) + { + emu_voice = &emu8k->voice[c]; + buf = &emu8k->buffer[emu8k->pos*2]; + + for (pos = emu8k->pos; pos < new_pos; pos++) + { + int32_t dat; + + /* Waveform oscillator */ + dat = EMU8K_READ_INTERP_LINEAR(emu8k, emu_voice->addr.int_address, + emu_voice->addr.fract_address); + + + /* Filter section */ + if (emu_voice->filterq_idx || emu_voice->cvcf_curr_filt_ctoff != 0xFFFF ) { + /* apply gain and move to 24bit. */ + int cutoff = emu_voice->cvcf_curr_filt_ctoff >> 8; + const int64_t coef0 = filt_coeffs[emu_voice->filterq_idx][cutoff][0]; + const int64_t coef1 = filt_coeffs[emu_voice->filterq_idx][cutoff][1]; + const int64_t coef2 = filt_coeffs[emu_voice->filterq_idx][cutoff][2]; + /* clip at twice the range */ + #define ClipBuffer(buf) (buf < -16777216) ? -16777216 : (buf > 16777216) ? 16777216 : buf + + #ifdef FILTER_INITIAL + #define NOOP(x) (void)x; + NOOP(coef1) + /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one doesn't). + Work in 23 bits + (at 24bits there's an integer overflow that I haven't been able to locate). */ + dat = (dat * emu_voice->filt_att) >> 8; + + int64_t vhp = ((-emu_voice->filt_buffer[0] * coef2) >> 24) - emu_voice->filt_buffer[1] - dat; + emu_voice->filt_buffer[1] += (emu_voice->filt_buffer[0] * coef0) >> 24; + emu_voice->filt_buffer[0] += (vhp * coef0) >> 24; + dat = (int32_t)(emu_voice->filt_buffer[1] >> 8); + if (dat > 32767) { dat = 32767; } + else if (dat < -32768) { dat = -32768; } + + #elif defined FILTER_MOOG + + /* move to 24bits */ + dat <<= 8; + + dat -= (coef2 * emu_voice->filt_buffer[4]) >> 24; /* feedback */ + int64_t t1 = emu_voice->filt_buffer[1]; + emu_voice->filt_buffer[1] = ((dat + emu_voice->filt_buffer[0]) * coef0 - emu_voice->filt_buffer[1] * coef1) >> 24; + emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]); + + int64_t t2 = emu_voice->filt_buffer[2]; + emu_voice->filt_buffer[2] = ((emu_voice->filt_buffer[1] + t1) * coef0 - emu_voice->filt_buffer[2] * coef1) >> 24; + emu_voice->filt_buffer[2] = ClipBuffer(emu_voice->filt_buffer[2]); + + int64_t t3 = emu_voice->filt_buffer[3]; + emu_voice->filt_buffer[3] = ((emu_voice->filt_buffer[2] + t2) * coef0 - emu_voice->filt_buffer[3] * coef1) >> 24; + emu_voice->filt_buffer[3] = ClipBuffer(emu_voice->filt_buffer[3]); + + emu_voice->filt_buffer[4] = ((emu_voice->filt_buffer[3] + t3) * coef0 - emu_voice->filt_buffer[4] * coef1) >> 24; + emu_voice->filt_buffer[4] = ClipBuffer(emu_voice->filt_buffer[4]); + + emu_voice->filt_buffer[0] = ClipBuffer(dat); + + dat = (int32_t)(emu_voice->filt_buffer[4] >> 8); + if (dat > 32767) { dat = 32767; } + else if (dat < -32768) { dat = -32768; } + + #elif defined FILTER_CONSTANT + + /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one is constant gain). Also stay at 24bits. */ + dat = (dat * emu_voice->filt_att) >> 8; + + emu_voice->filt_buffer[0] = (coef1 * emu_voice->filt_buffer[0] + + coef0 * (dat + + ((coef2 * (emu_voice->filt_buffer[0] - emu_voice->filt_buffer[1]))>>24)) + ) >> 24; + emu_voice->filt_buffer[1] = (coef1 * emu_voice->filt_buffer[1] + + coef0 * emu_voice->filt_buffer[0]) >> 24; + + emu_voice->filt_buffer[0] = ClipBuffer(emu_voice->filt_buffer[0]); + emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]); + + dat = (int32_t)(emu_voice->filt_buffer[1] >> 8); + if (dat > 32767) { dat = 32767; } + else if (dat < -32768) { dat = -32768; } + + #endif + + } + if (( emu8k->hwcf3 & 0x04) && !CCCA_DMA_ACTIVE(emu_voice->ccca)) + { + /* volume and pan */ + dat = (dat * emu_voice->cvcf_curr_volume) >> 16; + + (*buf++) += (dat * emu_voice->vol_l) >> 8; + (*buf++) += (dat * emu_voice->vol_r) >> 8; + + /* Effects section */ + if (emu_voice->ptrx_revb_send > 0) + { + /* TODO: Accumulate into reverb send buffer for processing after the voice loop */ + } + if (emu_voice->csl_chor_send > 0) + { + emu8k->chorus_in_buffer[pos]+=(dat*emu_voice->csl_chor_send) >> 8; + } + } + + if ( emu_voice->env_engine_on) { + + int32_t attenuation = emu_voice->initial_att; + int32_t filtercut = emu_voice->initial_filter; + int32_t currentpitch = emu_voice->ip; + /* run envelopes */ + emu8k_envelope_t *volenv = &emu_voice->vol_envelope; + switch (volenv->state) + { + case ENV_DELAY: + volenv->delay_samples--; + if (volenv->delay_samples <=0) + { + volenv->state=ENV_ATTACK; + } + attenuation = 0x1FFFFF; + break; + + case ENV_ATTACK: + /* Attack amount is in linear amplitude */ + volenv->value_amp_hz += volenv->attack_amount_amp_hz; + if (volenv->value_amp_hz >= (1 << 21)) + { + volenv->value_amp_hz = 1 << 21; + volenv->value_db_oct = 0; + if (volenv->hold_samples) + { + volenv->state = ENV_HOLD; + } + else + { + /* RAMP_UP since db value is inverted and it is 0 at this point. */ + volenv->state = ENV_RAMP_UP; + } + } + attenuation += env_vol_amplitude_to_db[volenv->value_amp_hz >> 5] << 5; + break; + + case ENV_HOLD: + volenv->hold_samples--; + if (volenv->hold_samples <=0) + { + volenv->state=ENV_RAMP_UP; + } + attenuation += volenv->value_db_oct; + break; + + case ENV_RAMP_DOWN: + /* Decay/release amount is in fraction of dBs and is always positive */ + volenv->value_db_oct -= volenv->ramp_amount_db_oct; + if (volenv->value_db_oct <= volenv->sustain_value_db_oct) + { + volenv->value_db_oct = volenv->sustain_value_db_oct; + volenv->state = ENV_SUSTAIN; + } + attenuation += volenv->value_db_oct; + break; + + case ENV_RAMP_UP: + /* Decay/release amount is in fraction of dBs and is always positive */ + volenv->value_db_oct += volenv->ramp_amount_db_oct; + if (volenv->value_db_oct >= volenv->sustain_value_db_oct) + { + volenv->value_db_oct = volenv->sustain_value_db_oct; + volenv->state = ENV_SUSTAIN; + } + attenuation += volenv->value_db_oct; + break; + + case ENV_SUSTAIN: + attenuation += volenv->value_db_oct; + break; + + case ENV_STOPPED: + attenuation = 0x1FFFFF; + break; + } + + emu8k_envelope_t *modenv = &emu_voice->mod_envelope; + switch (modenv->state) + { + case ENV_DELAY: + modenv->delay_samples--; + if (modenv->delay_samples <=0) + { + modenv->state=ENV_ATTACK; + } + break; + + case ENV_ATTACK: + /* Attack amount is in linear amplitude */ + modenv->value_amp_hz += modenv->attack_amount_amp_hz; + modenv->value_db_oct = env_mod_hertz_to_octave[modenv->value_amp_hz >> 5] << 5; + if (modenv->value_amp_hz >= (1 << 21)) + { + modenv->value_amp_hz = 1 << 21; + modenv->value_db_oct = 1 << 21; + if (modenv->hold_samples) + { + modenv->state = ENV_HOLD; + } + else + { + modenv->state = ENV_RAMP_DOWN; + } + } + break; + + case ENV_HOLD: + modenv->hold_samples--; + if (modenv->hold_samples <=0) + { + modenv->state=ENV_RAMP_UP; + } + break; + + case ENV_RAMP_DOWN: + /* Decay/release amount is in fraction of octave and is always positive */ + modenv->value_db_oct -= modenv->ramp_amount_db_oct; + if (modenv->value_db_oct <= modenv->sustain_value_db_oct) + { + modenv->value_db_oct = modenv->sustain_value_db_oct; + modenv->state = ENV_SUSTAIN; + } + break; + + case ENV_RAMP_UP: + /* Decay/release amount is in fraction of octave and is always positive */ + modenv->value_db_oct += modenv->ramp_amount_db_oct; + if (modenv->value_db_oct >= modenv->sustain_value_db_oct) + { + modenv->value_db_oct = modenv->sustain_value_db_oct; + modenv->state = ENV_SUSTAIN; + } + break; + } + + /* run lfos */ + if (emu_voice->lfo1_delay_samples) + { + emu_voice->lfo1_delay_samples--; + } + else + { + emu_voice->lfo1_count.addr += emu_voice->lfo1_speed; + emu_voice->lfo1_count.int_address &= 0xFFFF; + } + if (emu_voice->lfo2_delay_samples) + { + emu_voice->lfo2_delay_samples--; + } + else + { + emu_voice->lfo2_count.addr += emu_voice->lfo2_speed; + emu_voice->lfo2_count.int_address &= 0xFFFF; + } + + if (emu_voice->fixed_modenv_pitch_height) { + currentpitch += ((modenv->value_db_oct>>9)*emu_voice->fixed_modenv_pitch_height) >> 14; + } + + if (emu_voice->fixed_lfo1_vibrato) { + int32_t lfo1_vibrato = (lfotable[emu_voice->lfo1_count.int_address]*emu_voice->fixed_lfo1_vibrato) >> 17; + currentpitch += lfo1_vibrato; + } + if (emu_voice->fixed_lfo2_vibrato) { + int32_t lfo2_vibrato = (lfotable[emu_voice->lfo2_count.int_address]*emu_voice->fixed_lfo2_vibrato) >> 17; + currentpitch += lfo2_vibrato; + } + + if (emu_voice->fixed_modenv_filter_height) { + filtercut += ((modenv->value_db_oct>>9)*emu_voice->fixed_modenv_filter_height) >> 5; + } + + if (emu_voice->fixed_lfo1_filt_mod) { + int32_t lfo1_filtmod = (lfotable[emu_voice->lfo1_count.int_address]*emu_voice->fixed_lfo1_filt_mod) >> 9; + filtercut += lfo1_filtmod; + } + + if (emu_voice->fixed_lfo1_tremolo) { + int32_t lfo1_tremolo = (lfotable[emu_voice->lfo1_count.int_address]*emu_voice->fixed_lfo1_tremolo) >> 10; + attenuation += lfo1_tremolo; + } + + if (currentpitch > 0xFFFF) currentpitch = 0xFFFF; + if (currentpitch < 0) currentpitch = 0; + if (attenuation > 0x1FFFFF) attenuation = 0x1FFFFF; + if (attenuation < 0) attenuation = 0; + if (filtercut > 0x1FFFFF) filtercut = 0x1FFFFF; + if (filtercut < 0) filtercut = 0; + + emu_voice->vtft_vol_target = env_vol_db_to_vol_target[attenuation >> 5]; + emu_voice->vtft_filter_target = filtercut >> 5; + emu_voice->ptrx_pit_target = freqtable[currentpitch]>>18; + + /*if (modenv->state==ENV_ATTACK|| modenv->state==ENV_RAMP_UP|| modenv->state==ENV_RAMP_DOWN) { + pclog("EMUMODENV ch:%d %d:%08X - %08X : %08X - %08X\n", c, modenv->state, modenv->value_amp_hz, modenv->value_db_oct, modenv->attack_amount_amp_hz,modenv->ramp_amount_db_oct); + } + + if (emu_voice->fixed_modenv_pitch_height ||emu_voice->fixed_lfo1_vibrato || emu_voice->fixed_lfo2_vibrato) { + if (currentpitch!=old_pitch) { + pclog("EMUPitch ch:%d :%04X\n", c, currentpitch); + old_pitch=currentpitch; + } + } + if (emu_voice->fixed_modenv_filter_height ||emu_voice->fixed_lfo1_filt_mod) { + if (filtercut!=old_cut) { + pclog("EMUFilter ch:%d :%04X\n", c, filtercut); + old_cut=filtercut; + } + }*/ + } +/* +I've recopilated these sentences to get an idea of how to loop + +- Set its PSST register and its CLS register to zero to cause no loops to occur. +-Setting the Loop Start Offset and the Loop End Offset to the same value, will cause the oscillator to loop the entire memory. + +-Setting the PlayPosition greater than the Loop End Offset, will cause the oscillator to play in reverse, back to the Loop End Offset. It's pretty neat, but appears to be uncontrollable (the rate at which the samples are played in reverse). + +-Note that due to interpolator offset, the actual loop point is one greater than the start address +-Note that due to interpolator offset, the actual loop point will end at an address one greater than the loop address +-Note that the actual audio location is the point 1 word higher than this value due to interpolation offset +-In programs that use the awe, they generally set the loop address as "loopaddress -1" to compensate for the above. +(Note: I am already using address+1 in the interpolators so these things are already as they should.) +*/ + emu_voice->addr.addr += ((uint64_t)emu_voice->cpf_curr_pitch) << 18; + if (emu_voice->addr.addr >= emu_voice->loop_end.addr) + { + emu_voice->addr.int_address -= (emu_voice->loop_end.int_address - emu_voice->loop_start.int_address); + emu_voice->addr.int_address &= EMU8K_MEM_ADDRESS_MASK; + } + + /* TODO: How and when are the target and current values updated */ + emu_voice->cpf_curr_pitch = emu_voice->ptrx_pit_target; + emu_voice->cvcf_curr_volume = emu_voice->vtft_vol_target; + emu_voice->cvcf_curr_filt_ctoff = emu_voice->vtft_filter_target; + } + + /* Update EMU voice registers. */ + emu_voice->ccca = emu_voice->ccca_qcontrol | emu_voice->addr.int_address; + emu_voice->cpf_curr_frac_addr = emu_voice->addr.fract_address; + } + + + buf = &emu8k->buffer[emu8k->pos*2]; + emu8k_work_reverb(emu8k, new_pos); + emu8k_work_chorus(&emu8k->chorus_in_buffer[emu8k->pos], buf, &emu8k->chorus_engine, new_pos-emu8k->pos); + emu8k_work_eq(emu8k, new_pos); + + /* Clip signal */ + for (pos = emu8k->pos; pos < new_pos; pos++) + { + if (buf[0] < -32768) + buf[0] = -32768; + else if (buf[0] > 32767) + buf[0] = 32767; + + if (buf[1] < -32768) + buf[1] = -32768; + else if (buf[1] > 32767) + buf[1] = 32767; + + buf += 2; + } + + /* Update EMU clock. */ + emu8k->wc += (new_pos - emu8k->pos); + + emu8k->pos = new_pos; +} +/* onboard_ram in kilobytes */ void emu8k_init(emu8k_t *emu8k, int onboard_ram) { + uint32_t const BLOCK_SIZE_WORDS = 0x10000; FILE *f; int c; double out; - + f = romfopen(L"roms/sound/awe32.raw", L"rb"); if (!f) - fatal("ROMS/SOUND/AWE32.RAW not found\n"); + fatal("AWE32.RAW not found\n"); + emu8k->rom = malloc(1024 * 1024); + fread(emu8k->rom, 1024 * 1024, 1, f); + fclose(f); + /*AWE-DUMP creates ROM images offset by 2 bytes, so if we detect this + then correct it*/ + if (emu8k->rom[3] == 0x314d && emu8k->rom[4] == 0x474d) + { + memmove(&emu8k->rom[0], &emu8k->rom[1], (1024 * 1024) - 2); + emu8k->rom[0x7ffff] = 0; + } + + emu8k->empty = malloc(2*BLOCK_SIZE_WORDS); + memset(emu8k->empty, 0, 2*BLOCK_SIZE_WORDS); + + int j=0; + for (;j<0x8;j++) + { + emu8k->ram_pointers[j]=emu8k->rom+(j*BLOCK_SIZE_WORDS); + } + for (;j<0x20;j++) + { + emu8k->ram_pointers[j]=emu8k->empty; + } + if (onboard_ram) { /* Clip to 28MB, since that's the max that we can address. */ if (onboard_ram > 0x7000) onboard_ram = 0x7000; emu8k->ram = malloc(onboard_ram * 1024); - emu8k->ram_end_addr = EMU8K_RAM_MEM_START + ((onboard_ram * 1024) / 2); + memset(emu8k->ram, 0, onboard_ram * 1024); + const int i_end=onboard_ram>>7; + int i=0; + for(;iram_pointers[j]=emu8k->ram+(i*BLOCK_SIZE_WORDS); + } + emu8k->ram_end_addr = EMU8K_RAM_MEM_START + (onboard_ram<<9); } else { emu8k->ram = 0; emu8k->ram_end_addr = EMU8K_RAM_MEM_START; } - - emu8k->rom = malloc(1024 * 1024); - - fread(emu8k->rom, 1024 * 1024, 1, f); - fclose(f); - - /*AWE-DUMP creates ROM images offset by 2 bytes, so if we detect this - then correct it*/ - if (emu8k->rom[3] == 0x314d && emu8k->rom[4] == 0x474d) + for (;j < 0x100;j++) { - memcpy(&emu8k->rom[0], &emu8k->rom[1], (1024 * 1024) - 2); - emu8k->rom[0x7ffff] = 0; + emu8k->ram_pointers[j]=emu8k->empty; + } + io_sethandler(0x0620, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); io_sethandler(0x0a20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); io_sethandler(0x0e20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - /*Create frequency table*/ + /*Create frequency table. (Convert initial pitch register value to a linear speed change) + * The input is encoded such as 0xe000 is center note (no pitch shift) + * and from then on , changing up or down 0x1000 (4096) increments/decrements an octave. + * Note that this is in reference to the 44.1Khz clock that the channels play at. + * The 65536 * 65536 is in order to left-shift the 32bit value to a 64bit value as a 32.32 fixed point. + */ for (c = 0; c < 0x10000; c++) { freqtable[c] = (uint64_t)(exp2((double)(c - 0xe000) / 4096.0) * 65536.0 * 65536.0); } + /* Shortcut: minimum pitch equals stopped. I don't really know if this is true, but it's better + since some programs set the pitch to 0 for unused channels. */ + freqtable[0] = 0; - out = 65536.0; - + /* starting at 65535 because it is used for "volume target" register conversion. */ + out = 65535.0; for (c = 0; c < 256; c++) { - attentable[c] = (int)out; + attentable[c] = (int32_t)out; out /= sqrt(1.09018); /*0.375 dB steps*/ } + /* Shortcut: max attenuation is silent, not -96dB. */ + attentable[255]=0; - out = 65536; - - for (c = 0; c < 4096; c++) + /* Note: these two tables have "db" inverted: 0 dB is max volume, 65535 "db" (-96.32dBFS) is silence. + Important: Using 65535 as max output value because this is intended to be used with the volume target register! */ + out = 65535.0; + for (c = 0; c < 0x10000; c++) { - envtable[4095 - c] = (int)out; - out /= 1.002709201; /*0.0235 dB Steps*/ - } - - for (c = 0; c < 4096; c++) - { - int d = (c + 1024) & 4095; - if (d >= 2048) - lfotable[c] = 4096 - ((2048 - d) * 4); - else - lfotable[c] = (d * 4) - 4096; + env_vol_db_to_vol_target[c] = (int32_t)out; + /* calculated from the 65536th root of 65536 */ + out /= 1.00016923970; } + /* Shortcut: max attenuation is silent, not -96dB. */ + env_vol_db_to_vol_target[0x10000-1]=0; + /* One more position to forget about max value being 65536. */ + env_vol_db_to_vol_target[0x10000]=0; - out = 125.0; + for (c = 1; c < 0x10000; c++) + { + out = -680.32142884264* 20.0 * log10(c/65535.0); + env_vol_amplitude_to_db[c] = (int32_t)out; + } + /* Shortcut: max attenuation is silent, not -96dB. */ + env_vol_amplitude_to_db[0]=65535; + /* One more position to forget about max value being 65536. */ + env_vol_amplitude_to_db[0x10000]=0; + + + for (c = 1; c < 0x10000; c++) + { + out = log2((c/0x10000)+1.0) *65536.0; + env_mod_hertz_to_octave[c] = (int32_t)out; + } + /* No hertz change, no octave change. */ + env_mod_hertz_to_octave[0]=0; + /* One more position to forget about max value being 65536. */ + env_mod_hertz_to_octave[0x10000]=65536; + + + /* This formula comes from vince vu/judge dredd's awe32p10 and corresponds to what the freebsd/linux AWE32 driver has. */ + float millis; + for (c=0;c<128;c++) { + if (c==0) { + /* This means never attack. */ + millis = 0; + } + else if (c < 32) { + millis = 11878.0/c; + } else { + millis = 360*exp((c - 32) / (16.0/log(1.0/2.0))); + } + env_attack_to_samples[c] = 44.1*millis; + /* This is an alternate formula with linear increments, but probably incorrect: (256+4096*(0x7F-c)) */ + } + + /* The LFOs use a triangular waveform starting at zero and going 1/-1/1/-1. + This table is stored in signed 16bits precision, with a period of 65536 samples */ + for (c = 0; c < 65536; c++) + { + int d = (c + 16384) & 65535; + if (d >= 32768) + lfotable[c] = 32768 + ((32768 - d)*2); + else + lfotable[c] = (d*2) - 32768; + } + /* The 65536 * 65536 is in order to left-shift the 32bit value to a 64bit value as a 32.32 fixed point. */ + out = 0.01; for (c = 0; c < 256; c++) { -/* filt_w0[c] = (int32_t)((2.0 * 3.142 * (out / 44100.0)) * 0.707 * 256.0);*/ -/* filt_w0[c] = 2.0 * 3.142 * (out / 44100.0);*/ - filt_w0[c] = (int32_t)(2.0 * 3.142 * (out / 44100.0) * 256.0); - out *= 1.016378315; + lfofreqtospeed[c] = (uint64_t)(out *65536.0/44100.0 * 65536.0 * 65536.0); + out += 0.042; } + + /* Filter coefficients tables. Note: Values are multiplied by *16777216 to left shift 24 bits. (i.e. 8.24 fixed point) */ + int qidx; + for (qidx = 0; qidx < 16; qidx++) + { + out = 125.0; /* Start at 125Hz */ + for (c = 0; c < 256; c++) + { +#ifdef FILTER_INITIAL + float w0 = sin(2.0*M_PI*out / 44100.0); + /* The value 102.5f has been selected a bit randomly. Pretends to reach 0.2929 at w0 = 1.0 */ + float q = (qidx / 102.5f) * (1.0 + 1.0 / w0); + /* Limit max value. Else it would be 470. */ + if (q > 200) q=200; + filt_coeffs[qidx][c][0] = (int32_t)(w0 * 16777216.0); + filt_coeffs[qidx][c][1] = 16777216.0; + filt_coeffs[qidx][c][2] = (int32_t)((1.0f / (0.7071f + q)) * 16777216.0); +#elif defined FILTER_MOOG + float w0 = sin(2.0*M_PI*out / 44100.0); + float q_factor = 1.0f - w0; + float p = w0 + 0.8f * w0 * q_factor; + float f = p + p - 1.0f; + float resonance = (1.0-pow(2.0,-qidx*24.0/90.0))*0.8; + float q = resonance * (1.0f + 0.5f * q_factor * (w0 + 5.6f * q_factor * q_factor)); + filt_coeffs[qidx][c][0] = (int32_t)(p * 16777216.0); + filt_coeffs[qidx][c][1] = (int32_t)(f * 16777216.0); + filt_coeffs[qidx][c][2] = (int32_t)(q * 16777216.0); +#elif defined FILTER_CONSTANT + /* *16777216 to left shift 24 bits. */ + float q = (1.0-pow(2.0,-qidx*24.0/90.0))*0.8; + float coef0 = sin(2.0*M_PI*out / 44100.0); + float coef1 = 1.0 - coef0; + float coef2 = q * (1.0 + 1.0 / coef1); + filt_coeffs[qidx][c][0] = (int32_t)(coef0 * 16777216.0); + filt_coeffs[qidx][c][1] = (int32_t)(coef1 * 16777216.0); + filt_coeffs[qidx][c][2] = (int32_t)(coef2 * 16777216.0); +#endif /* FILTER_TYPE */ + /* 42.66 divisions per octave (the doc says quarter seminotes which is 48, but then it would be almost an octave less) */ + out *= 1.016378315; + } + } + + + /* Cubic Resampling ( 4point cubic spline) { */ + double const resdouble = 1.0/(double)CUBIC_RESOLUTION; + for(int i = 0; i < CUBIC_RESOLUTION; ++i) { + double x = (double)i * resdouble; + /* Cubic resolution is made of four table, but I've put them all in one table to optimize memory access. */ + cubic_table[i*4] = (int32_t)((-0.5 * x * x * x + x * x - 0.5 * x) *0x7FFF); + cubic_table[i*4+1] = (int32_t)(( 1.5 * x * x * x - 2.5 * x * x + 1.0) *0x7FFF); + cubic_table[i*4+2] = (int32_t)((-1.5 * x * x * x + 2.0 * x * x + 0.5 * x) *0x7FFF); + cubic_table[i*4+3] = (int32_t)(( 0.5 * x * x * x - 0.5 * x * x) *0x7FFF); + } + /* If this is not set here, AWE card is not detected on Windows with Aweman driver. It's weird that the EMU8k says that this + has to be set by applications, and the AWE driver does not set it. */ emu8k->hwcf1 = 0x59; emu8k->hwcf2 = 0x20; - emu8k->hwcf3 = 0x04; + /* Initial state is muted. 0x04 is unmuted. */ + emu8k->hwcf3 = 0x00; } void emu8k_close(emu8k_t *emu8k) @@ -779,3 +1943,4 @@ void emu8k_close(emu8k_t *emu8k) free(emu8k->rom); free(emu8k->ram); } + diff --git a/src/SOUND/snd_emu8k.h b/src/SOUND/snd_emu8k.h index 6eea70a00..ffd6a2600 100644 --- a/src/SOUND/snd_emu8k.h +++ b/src/SOUND/snd_emu8k.h @@ -1,69 +1,300 @@ +/* All these defines are in samples, not in bytes. */ #define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF #define EMU8K_RAM_MEM_START 0x200000 -#define EMU8K_ROM_MEM_1MB_END 0x80000 +#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0 +#define EMU8K_RAM_POINTERS_MASK 0x3F + +/* + Everything in this file assumes little endian + + used for the increment of oscillator position */ +typedef struct emu8k_mem_internal_t { + union { + uint64_t addr; + struct { + uint16_t fract_lw_address; + uint16_t fract_address; + uint32_t int_address; + }; + }; +} emu8k_mem_internal_t; + +/* used for access to ram pointers from oscillator position. */ +typedef struct emu8k_mem_pointers_t { + union { + uint32_t addr; + struct { + uint16_t lw_address; + uint8_t hb_address; + uint8_t unused_address; + }; + }; +} emu8k_mem_pointers_t; + +/* + * From the Soundfount 2.0 fileformat Spec.: + * + An envelope generates a control signal in six phases. + When key-on occurs, a delay period begins during which the envelope value is zero. + The envelope then rises in a convex curve to a value of one during the attack phase. + " Note that the attack is convex; the curve is nominally such that when applied to a + decibel or semitone parameter, the result is linear in amplitude or Hz respectively" + + When a value of one is reached, the envelope enters a hold phase during which it remains at one. + When the hold phase ends, the envelope enters a decay phase during which its value decreases linearly to a sustain level. + " For the Volume Envelope, the decay phase linearly ramps toward the sustain level, causing a constant dB change for each time unit. " + When the sustain level is reached, the envelope enters sustain phase, during which the envelope stays at the sustain level. + + Whenever a key-off occurs, the envelope immediately enters a release phase during which the value linearly ramps from the current value to zero. + " For the Volume Envelope, the release phase linearly ramps toward zero from the current level, causing a constant dB change for each time unit" + + When zero is reached, the envelope value remains at zero. + + Modulation of pitch and filter cutoff are in octaves, semitones, and cents. + These parameters can be modulated to varying degree, either positively or negatively, by the modulation envelope. + The degree of modulation is specified in cents for the full-scale attack peak. + + The volume envelope operates in dB, with the attack peak providing a full scale output, appropriately scaled by the initial volume. + The zero value, however, is actually zero gain. + The implementation in the EMU8000 provides for 96 dB of amplitude control. + When 96 dB of attenuation is reached in the final gain amplifier, an abrupt jump to zero gain (infinite dB of attenuation) occurs. In a 16-bit system, this jump is inaudible +*/ +/* It seems that the envelopes don't really have a decay/release stage, + but instead they have a volume ramper that can be triggered + automatically (after hold period), or manually (by activating release) + and the "sustain" value is the target of any of both cases. + Some programs like cubic player and AWEAmp use this, and it was + described in the following way in Vince Vu/Judge Dredd's awe32p10.txt: + If the MSB (most significant bit or bit 15) of this register is set, + the Decay/Release will begin immediately, overriding the Delay, Attack, + and Hold. Otherwise the Decay/Release will wait until the Delay, Attack, + and Hold are finished. If you set the MSB of this register, you can use + it as a volume ramper, as on the GUS. The upper byte (except the MSB), + contains the destination volume, and the lower byte contains the ramp time. */ + +/* attack_amount is linear amplitude (added directly to value). ramp_amount_db is linear dB (added directly to value too, but needs conversion to get linear amplitude). + value range is 21bits for both, linear amplitude being 1<<21 = 0dBFS and 0 = -96dBFS (which is shortcut to silence), and db amplutide being 0 = 0dBFS and -(1<<21) = -96dBFS (which is shortcut to silence). This allows to operate db values by simply adding them. */ +typedef struct emu8k_envelope_t { + int state; + int32_t delay_samples, hold_samples, attack_samples; + int32_t value_amp_hz, value_db_oct; + int32_t sustain_value_db_oct; + int32_t attack_amount_amp_hz, ramp_amount_db_oct; +} emu8k_envelope_t; + + + +/* Chorus Params */ +typedef struct { + uint16_t FbkLevReg; /* Feedback Level (0xE600-0xE6FF) */ + uint16_t Delay; /* Delay (0-0x0DA3) [1/44100 sec] */ + uint16_t LfoDepReg; /* LFO Depth (0xBC00-0xBCFF) */ + uint32_t DelayR; /* Right Delay (0-0xFFFFFFFF) [1/256/44100 sec] */ + uint32_t LfoFreq; /* LFO Frequency (0-0xFFFFFFFF) */ +} emu8k_chorus_t; + +typedef struct { + int32_t write; + int32_t feedback; + int32_t delay_samples_central; + int32_t lfodepth_samples; + emu8k_mem_internal_t delay_offset_samples_right; + emu8k_mem_internal_t lfo_inc; + emu8k_mem_internal_t lfo_pos; + + int32_t chorus_left_buffer[SOUNDBUFLEN]; + int32_t chorus_right_buffer[SOUNDBUFLEN]; + +} emu8k_chorus_eng_t; + +typedef struct emu8k_voice_t +{ + union { + uint32_t cpf; + struct { + uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */ + uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */ + }; + }; + union { + uint32_t ptrx; + struct { + uint8_t ptrx_pan_aux; + uint8_t ptrx_revb_send; + uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */ + }; + }; + union { + uint32_t cvcf; + struct { + uint16_t cvcf_curr_filt_ctoff; + uint16_t cvcf_curr_volume; + }; + }; + union { + uint32_t vtft; + struct { + uint16_t vtft_filter_target; + uint16_t vtft_vol_target; /* written to by the envelope engine. */ + }; + }; + /* These registers are used at least by the Windows drivers, and seem to be resetting + something, similarly to targets and current, but... of what? + what is curious is that if they are already zero, they are not written to, so it really + looks like they are information about the status of the channel. (lfo position maybe?) */ + uint32_t unknown_data0_4; + uint32_t unknown_data0_5; + union { + uint32_t psst; + struct { + uint16_t psst_lw_address; + uint8_t psst_hw_address; + uint8_t psst_pan; + }; + #define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */ + }; + union { + uint32_t csl; + struct { + uint16_t csl_lw_address; + uint8_t csl_hw_address; + uint8_t csl_chor_send; + }; + #define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */ + }; + union { + uint32_t ccca; + struct { + uint16_t ccca_lw_addr; + uint8_t ccca_hb_addr; + uint8_t ccca_qcontrol; + }; + }; + #define CCCA_FILTQ_GET(ccca) (ccca>>28) + #define CCCA_FILTQ_SET(ccca,q) ccca = (ccca&0x0FFFFFFF) | (q<<28) + /* Bit 27 should always be zero */ + #define CCCA_DMA_ACTIVE(ccca) (ccca&0x04000000) + #define CCCA_DMA_WRITE_MODE(ccca) (ccca&0x02000000) + #define CCCA_DMA_WRITE_RIGHT(ccca) (ccca&0x01000000) + + uint16_t envvol; + #define ENVVOL_NODELAY(envol) (envvol&0x8000) + /* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */ + #define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol&0x8000) ? 0 : ((0x8000-(envvol&0x7FFF)) <<5) + + uint16_t dcysusv; + #define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv&0x8000) + #define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv&0x0080) + #define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv>>8)&0x7F) + /* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */ + #define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F-susvalue) << 21)/0x7F) + #define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv&0x7F) + + uint16_t envval; + #define ENVVAL_NODELAY(enval) (envval&0x8000) + /* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */ + #define ENVVAL_TO_EMU_SAMPLES(envval)(envval&0x8000) ? 0 : ((0x8000-(envval&0x7FFF)) <<5) + + uint16_t dcysus; + #define DCYSUS_IS_RELEASE(dcysus) (dcysus&0x8000) + #define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus>>8)&0x7F) + #define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21)/0x7F) + #define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus&0x7F) + + uint16_t atkhldv; + #define ATKHLDV_TRIGGER(atkhldv) !(atkhldv&0x8000) + #define ATKHLDV_HOLD(atkhldv) ((atkhldv>>8)&0x7F) + #define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096*(0x7F-((atkhldv>>8)&0x7F))) + #define ATKHLDV_ATTACK(atkhldv) (atkhldv&0x7F) + + uint16_t lfo1val, lfo2val; + #define LFOxVAL_NODELAY(lfoxval) (lfoxval&0x8000) + #define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval&0x8000) ? 0 : ((0x8000-(lfoxval&0x7FFF)) <<5) + + uint16_t atkhld; + #define ATKHLD_TRIGGER(atkhld) !(atkhld&0x8000) + #define ATKHLD_HOLD(atkhld) ((atkhld>>8)&0x7F) + #define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096*(0x7F-((atkhld>>8)&0x7F))) + #define ATKHLD_ATTACK(atkhld) (atkhld&0x7F) + + + uint16_t ip; + #define INTIAL_PITCH_CENTER 0xE000 + #define INTIAL_PITCH_OCTAVE 0x1000 + + union { + uint16_t ifatn; + struct{ + uint8_t ifatn_attenuation; + uint8_t ifatn_init_filter; + }; + }; + union { + uint16_t pefe; + struct { + int8_t pefe_modenv_filter_height; + int8_t pefe_modenv_pitch_height; + }; + }; + union { + uint16_t fmmod; + struct { + int8_t fmmod_lfo1_filt_mod; + int8_t fmmod_lfo1_vibrato; + }; + }; + union { + uint16_t tremfrq; + struct { + uint8_t tremfrq_lfo1_freq; + int8_t tremfrq_lfo1_tremolo; + }; + }; + union { + uint16_t fm2frq2; + struct { + uint8_t fm2frq2_lfo2_freq; + int8_t fm2frq2_lfo2_vibrato; + }; + }; + + int env_engine_on; + + emu8k_mem_internal_t addr, loop_start, loop_end; + + int32_t initial_att; + int32_t initial_filter; + + emu8k_envelope_t vol_envelope; + emu8k_envelope_t mod_envelope; + + int64_t lfo1_speed, lfo2_speed; + emu8k_mem_internal_t lfo1_count, lfo2_count; + int32_t lfo1_delay_samples, lfo2_delay_samples; + int vol_l, vol_r; + + int16_t fixed_modenv_filter_height; + int16_t fixed_modenv_pitch_height; + int16_t fixed_lfo1_filt_mod; + int16_t fixed_lfo1_vibrato; + int16_t fixed_lfo1_tremolo; + int16_t fixed_lfo2_vibrato; + + /* filter internal data. */ + int filterq_idx; + int32_t filt_att; + int64_t filt_buffer[5]; + +} emu8k_voice_t; typedef struct emu8k_t { - struct - { - uint32_t cpf; - uint32_t ptrx; - uint32_t cvcf; - uint32_t vtft; - uint32_t psst; - uint32_t csl; - - uint32_t ccca; + emu8k_voice_t voice[32]; - uint16_t init1, init2, init3, init4; - - uint16_t envvol; - uint16_t dcysusv; - uint16_t envval; - uint16_t dcysus; - uint16_t atkhldv; - uint16_t lfo1val, lfo2val; - uint16_t atkhld; - uint16_t ip; - uint16_t ifatn; - uint16_t pefe; - uint16_t fmmod; - uint16_t tremfrq; - uint16_t fm2frq2; - - int voice_on; - - uint64_t addr; - uint64_t loop_start, loop_end; - - uint16_t pitch; - int attenuation; - int env_state, env_vol; - int env_attack, env_decay, env_sustain, env_release; + uint16_t hwcf1, hwcf2, hwcf3; + uint32_t hwcf4, hwcf5, hwcf6, hwcf7; - int menv_state, menv_vol; - int menv_attack, menv_decay, menv_sustain, menv_release; - - int lfo1_count, lfo2_count; - int8_t lfo1_fmmod, lfo2_fmmod; - int8_t lfo1_trem; - int vol_l, vol_r; - - int8_t fe_height; - - int64_t vlp, vbp, vhp; - int32_t q; - - int filter_offset; - -/* float vlp, vbp, vhp; - float q;*/ - - int cutoff; - } voice[32]; - - uint32_t hwcf1, hwcf2, hwcf3; - uint32_t hwcf4, hwcf5, hwcf6; + uint16_t init1[32], init2[32], init3[32], init4[32]; uint32_t smalr, smarr, smalw, smarw; uint16_t smld_buffer, smrd_buffer; @@ -72,22 +303,32 @@ typedef struct emu8k_t uint16_t c02_read; - uint16_t id; - - int16_t *ram, *rom; - + uint16_t id; + + /* The empty block is used to act as an unallocated memory returning zero. */ + int16_t *ram, *rom, *empty; + + /* RAM pointers are a way to avoid checking ram boundaries on read */ + int16_t *ram_pointers[0x100]; uint32_t ram_end_addr; - + int cur_reg, cur_voice; int timer_count; int16_t out_l, out_r; + emu8k_chorus_eng_t chorus_engine; + int32_t chorus_in_buffer[SOUNDBUFLEN]; + int32_t reverb_in_buffer[SOUNDBUFLEN]; + int32_t reverb_out_buffer[SOUNDBUFLEN * 2]; + int pos; int32_t buffer[SOUNDBUFLEN * 2]; } emu8k_t; + + void emu8k_init(emu8k_t *emu8k, int onboard_ram); void emu8k_close(emu8k_t *emu8k); diff --git a/src/WIN/86Box.rc b/src/WIN/86Box.rc index bea1d7164..991b8bfe5 100644 --- a/src/WIN/86Box.rc +++ b/src/WIN/86Box.rc @@ -703,12 +703,12 @@ BEGIN IDS_2053 "Invalid number of sectors (valid values are between 1 and 63)" IDS_2054 "Invalid number of heads (valid values are between 1 and 16)" IDS_2055 "Invalid number of cylinders (valid values are between 1 and 266305)" - IDS_2056 "Please enter a valid file name" - IDS_2057 "Unable to open the file for write" - IDS_2058 "Attempting to create a HDI image larger than 4 GB" - IDS_2059 "Remember to partition and format the new drive" - IDS_2060 "Unable to open the file for read" - IDS_2061 "HDI or HDX image with a sector size that is not 512 are not supported" + IDS_2056 "Specify the NVR Path" + IDS_2057 "(empty)" + IDS_2058 "(host drive %c:)" + IDS_2059 "Turbo" + IDS_2060 "On" + IDS_2061 "Off" IDS_2062 "86Box was unable to find any ROMs.\nAt least one ROM set is required to use 86Box." IDS_2063 "Configured ROM set not available.\nDefaulting to an available ROM set." END @@ -724,9 +724,8 @@ BEGIN IDS_2070 "Other peripherals" IDS_2071 "Hard disks" IDS_2072 "Removable devices" - IDS_2073 "%i"" floppy drive: %s" - IDS_2074 "Disabled CD-ROM drive" - IDS_2075 "%s CD-ROM drive: %s" + IDS_2073 "Unable to create bitmap file: %s" + IDS_2074 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" IDS_2076 "Host CD/DVD Drive (%c:)" IDS_2077 "Click to capture mouse" IDS_2078 "Press F12-F8 to release mouse" @@ -743,14 +742,12 @@ BEGIN IDS_2085 "H" IDS_2086 "S" IDS_2087 "MB" - IDS_2088 "%i" IDS_2089 "Enabled" IDS_2090 "Mute" IDS_2091 "Type" IDS_2092 "Bus" IDS_2093 "DMA" IDS_2094 "KB" - IDS_2095 "MFM, RLL, or ESDI CD-ROM drives never existed" END STRINGTABLE DISCARDABLE @@ -766,7 +763,6 @@ BEGIN IDS_2104 "Network Type" IDS_2105 "Surround Module" IDS_2106 "MPU-401 Base Address" - IDS_2107 "No PCap devices found" IDS_2108 "On-board RAM" IDS_2109 "Memory Size" IDS_2110 "Display Type" @@ -806,15 +802,15 @@ BEGIN IDS_2136 "Slow VLB/PCI" IDS_2137 "Mid VLB/PCI" IDS_2138 "Fast VLB/PCI" - IDS_2139 "Microsoft 2-button mouse (serial)" - IDS_2140 "Mouse Systems mouse (serial)" - IDS_2141 "2-button mouse (PS/2)" - IDS_2142 "Microsoft Intellimouse (PS/2)" - IDS_2143 "Bus mouse" END STRINGTABLE DISCARDABLE BEGIN + IDS_2139 "PCap failed to set up because it may not be initialized" + IDS_2140 "No PCap devices found" + IDS_2141 "Invalid PCap device" + IDS_2142 "&Notify disk change" + IDS_2143 "Type" IDS_2144 "Standard 2-button joystick(s)" IDS_2145 "Standard 4-button joystick" IDS_2146 "Standard 6-button joystick" @@ -822,85 +818,95 @@ BEGIN IDS_2148 "CH Flightstick Pro" IDS_2149 "Microsoft SideWinder Pad" IDS_2150 "Thrustmaster Flight Control System" - IDS_2151 "Disabled" + IDS_2151 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" IDS_2152 "None" IDS_2153 "AT Fixed Disk Adapter" IDS_2154 "Internal IDE" IDS_2155 "IRQ %i" - IDS_2156 "MFM (%01i:%01i)" - IDS_2157 "IDE (PIO+DMA) (%01i:%01i)" - IDS_2158 "SCSI (%02i:%02i)" - IDS_2159 "Invalid number of cylinders (valid values are between 1 and 1023)" - IDS_2160 "%" PRIu64 - IDS_2161 "Genius Bus mouse" - IDS_2162 "Amstrad mouse" - IDS_2163 "Attempting to create a spuriously large hard disk image" - IDS_2164 "Invalid number of sectors (valid values are between 1 and 99)" - IDS_2165 "MFM" - IDS_2166 "XT IDE" - IDS_2167 "RLL" - IDS_2168 "IDE (PIO-only)" - IDS_2169 "%01i:%01i" - IDS_2170 "Custom..." - IDS_2171 "%" PRIu64 " MB (CHS: %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")" - IDS_2172 "Hard disk images (*.HDI;*.HDX;*.IMA;*.IMG)\0*.HDI;*.HDX;*.IMA;*.IMG\0All files (*.*)\0*.*\0" - IDS_2173"All floppy images (*.0??;*.12;*.144;*.360;*.720;*.86F;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMD;*.IMG;*.TD0;*.VFD;*.XDF)\0*.0??;*.12;*.144;*.360;*.720;*.86F;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMD;*.IMG;*.TD0;*.VFD;*.XDF\0Advanced sector-based images (*.IMD;*.TD0)\0*.IMD;*.TD0\0Basic sector-based images (*.0??;*.12;*.144;*.360;*.720;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMG;*.VFD;*.XDF)\0*.0??;*.12;*.144;*.360;*.720;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMG;*.VFD;*.XDF\0Flux images (*.FDI)\0*.FDI\0Surface-based images (*.86F)\0*.86F\0All files (*.*)\0*.*\0" - IDS_2174 "Configuration files (*.CFG)\0*.CFG\0All files (*.*)\0*.*\0" - IDS_2175 "CD-ROM image (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" - IDS_2176 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" - IDS_2177 "Olivetti M24 mouse" - IDS_2178 "This image exists and will be overwritten.\nAre you sure you want to use it?" - IDS_2179 "Floppy %i (%s): %ws" - IDS_2180 "CD-ROM %i: %ws" - IDS_2181 "MFM hard disk" - IDS_2182 "IDE hard disk (PIO-only)" - IDS_2183 "IDE hard disk (PIO and DMA)" - IDS_2184 "SCSI hard disk" - IDS_2185 "(empty)" - IDS_2186 "(host drive %c:)" - IDS_2187 "Custom (large)..." - IDS_2188 "Type" - IDS_2189 "ATAPI (PIO-only)" - IDS_2190 "ATAPI (PIO and DMA)" - IDS_2191 "ATAPI (PIO-only) (%01i:%01i)" - IDS_2192 "ATAPI (PIO and DMA) (%01i:%01i)" - IDS_2193 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" - IDS_2194 "Unable to create bitmap file: %s" - IDS_2195 "IDE (PIO-only) (%01i:%01i)" - IDS_2196 "Add New Hard Disk" - IDS_2197 "Add Existing Hard Disk" - IDS_2198 "SCSI removable disk %i: %s" - IDS_2199 "USB is not yet supported" - IDS_2200 "Invalid PCap device" - IDS_2201 "&Notify disk change" - IDS_2202 "SCSI (removable)" - IDS_2203 "SCSI (removable) (%02i:%02i)" - IDS_2204 "Pcap Library Not Available" - IDS_2205 "RLL (%01i:%01i)" - IDS_2206 "XT IDE (%01i:%01i)" - IDS_2207 "RLL hard disk" - IDS_2208 "XT IDE hard disk" - IDS_2209 "IDE (PIO and DMA)" - IDS_2210 "SCSI" - IDS_2211 "&New image..." - IDS_2212 "Existing image..." - IDS_2213 "Existing image (&Write-protected)..." - IDS_2214 "E&ject" - IDS_2215 "&Mute" - IDS_2216 "E&mpty" - IDS_2217 "&Reload previous image" - IDS_2218 "&Image..." - IDS_2219 "PCap failed to set up because it may not be initialized" - IDS_2220 "Image (&Write-protected)..." - IDS_2221 "Turbo" - IDS_2222 "On" - IDS_2223 "Off" - IDS_2224 "Logitech 3-button mouse (serial)" - IDS_2225 "Specify the NVR Path" - IDS_2226 "" - IDS_2227 "English (United States)" + IDS_2156 "%" PRIu64 + IDS_2157 "%" PRIu64 " MB (CHS: %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")" + IDS_2158 "Floppy %i (%s): %ws" + IDS_2159"All floppy images (*.0??;*.12;*.144;*.360;*.720;*.86F;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMD;*.IMG;*.TD0;*.VFD;*.XDF)\0*.0??;*.12;*.144;*.360;*.720;*.86F;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMD;*.IMG;*.TD0;*.VFD;*.XDF\0Advanced sector-based images (*.IMD;*.TD0)\0*.IMD;*.TD0\0Basic sector-based images (*.0??;*.12;*.144;*.360;*.720;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMG;*.VFD;*.XDF)\0*.0??;*.12;*.144;*.360;*.720;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMG;*.VFD;*.XDF\0Flux images (*.FDI)\0*.FDI\0Surface-based images (*.86F)\0*.86F\0All files (*.*)\0*.*\0" + IDS_2160 "Configuration files (*.CFG)\0*.CFG\0All files (*.*)\0*.*\0" + IDS_2161 "&New image..." + IDS_2162 "Existing image..." + IDS_2163 "Existing image (&Write-protected)..." + IDS_2164 "E&ject" + IDS_2165 "&Mute" + IDS_2166 "E&mpty" + IDS_2167 "&Reload previous image" + IDS_2168 "&Image..." + IDS_2169 "Image (&Write-protected)..." + + IDS_3072 "None" + IDS_3073 "[Bus] Bus mouse" + IDS_3074 "[Serial] Mouse Systems mouse" + IDS_3075 "[Serial] Microsoft 2-button mouse" + IDS_3076 "[Serial] Logitech 3-button mouse" + IDS_3077 "[Serial] Microsoft wheel mouse" + IDS_3078 "[PS/2] 2-button mouse" + IDS_3079 "[PS/2] Microsoft Intellimouse" + IDS_3080 "[Proprietary] Amstrad mouse" + IDS_3081 "[Proprietary] Olivetti M24 mouse" + + IDS_4096 "Hard disk (%s)" + IDS_4097 "%01i:%01i" + IDS_4098 "%i" + IDS_4099 "Disabled" + IDS_4100 "Custom..." + IDS_4101 "Custom (large)..." + IDS_4102 "Add New Hard Disk" + IDS_4103 "Add Existing Hard Disk" + IDS_4104 "Attempting to create a HDI image larger than 4 GB" + IDS_4105 "Attempting to create a spuriously large hard disk image" + IDS_4106 "Hard disk images (*.HDI;*.HDX;*.IMA;*.IMG)\0*.HDI;*.HDX;*.IMA;*.IMG\0All files (*.*)\0*.*\0" + IDS_4107 "Unable to open the file for read" + IDS_4108 "Unable to open the file for write" + IDS_4109 "HDI or HDX image with a sector size that is not 512 are not supported" + IDS_4110 "USB is not yet supported" + IDS_4111 "This image exists and will be overwritten.\nAre you sure you want to use it?" + IDS_4112 "Please enter a valid file name" + IDS_4113 "Remember to partition and format the new drive" + IDS_4114 "MFM or ESDI CD-ROM drives never existed" + IDS_4115 "Removable disk %i (SCSI): %ws" + + IDS_4352 "MFM" + IDS_4353 "XT IDE" + IDS_4354 "ESDI" + IDS_4355 "IDE (PIO-only)" + IDS_4356 "IDE (PIO+DMA)" + IDS_4357 "SCSI" + IDS_4358 "SCSI (removable)" + + IDS_4608 "MFM (%01i:%01i)" + IDS_4609 "XT IDE (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (PIO-only) (%01i:%01i)" + IDS_4612 "IDE (PIO+DMA) (%01i:%01i)" + IDS_4613 "SCSI (%02i:%02i)" + IDS_4614 "SCSI (removable) (%02i:%02i)" + + IDS_5120 "CD-ROM %i (%s): %s" + + IDS_5376 "Disabled" + IDS_5377 "" + IDS_5378 "" + IDS_5379 "" + IDS_5380 "ATAPI (PIO-only)" + IDS_5381 "ATAPI (PIO and DMA)" + IDS_5382 "SCSI" + + IDS_5632 "Disabled" + IDS_5633 "" + IDS_5634 "" + IDS_5635 "" + IDS_5636 "ATAPI (PIO-only) (%01i:%01i)" + IDS_5637 "ATAPI (PIO and DMA) (%01i:%01i)" + IDS_5638 "SCSI (%02i:%02i)" + + IDS_6144 "English (United States)" END -#define IDS_LANG_ENUS IDS_2227 +#define IDS_LANG_ENUS IDS_6144 #ifndef _MAC diff --git a/src/WIN/plat_ui.h b/src/WIN/plat_ui.h index 7bc6d35d9..120a04e55 100644 --- a/src/WIN/plat_ui.h +++ b/src/WIN/plat_ui.h @@ -17,6 +17,10 @@ extern wchar_t *plat_get_string_from_id(int i); #ifndef IDS_2079 #define IDS_2079 2079 #endif + +#ifndef IDS_2139 +#define IDS_2139 2139 +#endif #endif extern void plat_msgbox_fatal(char *string); diff --git a/src/WIN/resource.h b/src/WIN/resource.h index 02fa21a9f..9fa250250 100644 --- a/src/WIN/resource.h +++ b/src/WIN/resource.h @@ -288,11 +288,11 @@ #define IDS_2136 2136 // "Slow VLB/PCI" #define IDS_2137 2137 // "Mid VLB/PCI" #define IDS_2138 2138 // "Fast VLB/PCI" -#define IDS_2139 2139 // "Microsoft 2-button mouse (serial)" -#define IDS_2140 2140 // "Mouse Systems mouse (serial)" -#define IDS_2141 2141 // "2-button mouse (PS/2)" -#define IDS_2142 2142 // "Microsoft Intellimouse (PS/2)" -#define IDS_2143 2143 // "Bus mouse" +#define IDS_2139 2139 +#define IDS_2140 2140 +#define IDS_2141 2141 +#define IDS_2142 2142 +#define IDS_2143 2143 #define IDS_2144 2144 // "Standard 2-button joystick(s)" #define IDS_2145 2145 // "Standard 4-button joystick" #define IDS_2146 2146 // "Standard 6-button joystick" @@ -310,8 +310,8 @@ #define IDS_2158 2158 // "SCSI (%02i:%02i)" #define IDS_2159 2159 // "Invalid number of cylinders.." #define IDS_2160 2160 // "%" PRIu64 -#define IDS_2161 2161 // "Genius Bus mouse" -#define IDS_2162 2162 // "Amstrad mouse" +#define IDS_2161 2161 +#define IDS_2162 2162 #define IDS_2163 2163 // "Attempting to create a spuriously.." #define IDS_2164 2164 // "Invalid number of sectors.." #define IDS_2165 2165 // "MFM" @@ -319,67 +319,86 @@ #define IDS_2167 2167 // "RLL" #define IDS_2168 2168 // "IDE (PIO-only)" #define IDS_2169 2169 // "%01i:%01i" -#define IDS_2170 2170 // "Custom..." -#define IDS_2171 2171 // "%" PRIu64 " MB (CHS: %" .. -#define IDS_2172 2172 // "Hard disk images .." -#define IDS_2173 2173 // "All floppy images .." -#define IDS_2174 2174 // "Configuration files .." -#define IDS_2175 2175 // "CD-ROM image .." -#define IDS_2176 2176 // "Use CTRL+ALT+PAGE DOWN .." -#define IDS_2177 2177 // "Olivetti M24 mouse" -#define IDS_2178 2178 // "This image exists and will.." -#define IDS_2179 2179 // "Floppy %i (%s): %ws" -#define IDS_2180 2180 // "CD-ROM %i: %ws" -#define IDS_2181 2181 // "MFM hard disk" -#define IDS_2182 2182 // "IDE hard disk (PIO-only)" -#define IDS_2183 2183 // "IDE hard disk (PIO and DMA)" -#define IDS_2184 2184 // "SCSI hard disk" -#define IDS_2185 2185 // "(empty)" -#define IDS_2186 2186 // "(host drive %c:)" -#define IDS_2187 2187 // "Custom (large)..." -#define IDS_2188 2188 // "Type" -#define IDS_2189 2189 // "ATAPI (PIO-only)" -#define IDS_2190 2190 // "ATAPI (PIO and DMA)" -#define IDS_2191 2191 // "ATAPI (PIO-only) (%01i:%01i)" -#define IDS_2192 2192 // "ATAPI (PIO and DMA) (%01i:%01i)" -#define IDS_2193 2193 // "Use CTRL+ALT+PAGE DOWN to .." -#define IDS_2194 2194 // "Unable to create bitmap file: %s" -#define IDS_2195 2195 // "IDE (PIO-only) (%01i:%01i)" -#define IDS_2196 2196 // "Add New Hard Disk" -#define IDS_2197 2197 // "Add Existing Hard Disk" -#define IDS_2198 2198 // "SCSI removable disk %i: %s" -#define IDS_2199 2199 // "USB is not yet supported" -#define IDS_2200 2200 // "Invalid PCap device" -#define IDS_2201 2201 // "&Notify disk change" -#define IDS_2202 2202 // "SCSI (removable)" -#define IDS_2203 2203 // "SCSI (removable) (%02i:%02i)" -#define IDS_2204 2204 // "Pcap Library Not Available" -#define IDS_2205 2205 // "RLL (%01i:%01i)" -#define IDS_2206 2206 // "XT IDE (%01i:%01i)" -#define IDS_2207 2207 // "RLL hard disk" -#define IDS_2208 2208 // "XT IDE hard disk" -#define IDS_2209 2209 // "IDE (PIO and DMA)" -#define IDS_2210 2210 // "SCSI" -#define IDS_2211 2211 // "&New image..." -#define IDS_2212 2212 // "Existing image..." -#define IDS_2213 2213 // "Existing image (&Write-.." -#define IDS_2214 2214 // "E&ject" -#define IDS_2215 2215 // "&Mute" -#define IDS_2216 2216 // "E&mpty" -#define IDS_2217 2217 // "&Reload previous image" -#define IDS_2218 2218 // "&Image..." -#define IDS_2219 2219 // "PCap failed to set up .." -#define IDS_2220 2220 // "Image (&Write-protected)..." -#define IDS_2221 2221 // "Turbo" -#define IDS_2222 2222 // "On" -#define IDS_2223 2223 // "Off" -#define IDS_2224 2224 // "Logitech 3-button mouse (serial)" -#define IDS_2225 2225 // "Specify the NVR Path" -#define IDS_2226 2226 // "" -#define IDS_2227 2227 // "English (United States)" -#define IDS_LANG_ENUS IDS_2227 -#define STRINGS_NUM 180 +#define IDS_3072 3072 +#define IDS_3073 3073 +#define IDS_3074 3074 +#define IDS_3075 3075 +#define IDS_3076 3076 +#define IDS_3077 3077 +#define IDS_3078 3078 +#define IDS_3079 3079 +#define IDS_3080 3080 +#define IDS_3081 3081 + +#define IDS_4096 4096 +#define IDS_4097 4097 +#define IDS_4098 4098 +#define IDS_4099 4099 +#define IDS_4100 4100 +#define IDS_4101 4101 +#define IDS_4102 4102 +#define IDS_4103 4103 +#define IDS_4104 4104 +#define IDS_4105 4105 +#define IDS_4106 4106 +#define IDS_4107 4107 +#define IDS_4108 4108 +#define IDS_4109 4109 +#define IDS_4110 4110 +#define IDS_4111 4111 +#define IDS_4112 4112 +#define IDS_4113 4113 +#define IDS_4114 4114 +#define IDS_4115 4115 + +#define IDS_4352 4352 +#define IDS_4353 4353 +#define IDS_4354 4354 +#define IDS_4355 4355 +#define IDS_4356 4356 +#define IDS_4357 4357 +#define IDS_4358 4358 + +#define IDS_4608 4608 +#define IDS_4609 4609 +#define IDS_4610 4610 +#define IDS_4611 4611 +#define IDS_4612 4612 +#define IDS_4613 4613 +#define IDS_4614 4614 + +#define IDS_5120 5120 + +#define IDS_5376 5376 +#define IDS_5377 5377 +#define IDS_5378 5378 +#define IDS_5379 5379 +#define IDS_5380 5380 +#define IDS_5381 5381 +#define IDS_5382 5382 + +#define IDS_5632 5632 +#define IDS_5633 5633 +#define IDS_5634 5634 +#define IDS_5635 5635 +#define IDS_5636 5636 +#define IDS_5637 5637 +#define IDS_5638 5638 + +#define IDS_6144 6144 + +#define IDS_LANG_ENUS IDS_6144 + +#define STRINGS_NUM_2048 122 +#define STRINGS_NUM_3072 10 +#define STRINGS_NUM_4096 20 +#define STRINGS_NUM_4352 7 +#define STRINGS_NUM_4608 7 +#define STRINGS_NUM_5120 1 +#define STRINGS_NUM_5376 7 +#define STRINGS_NUM_5632 7 +#define STRINGS_NUM_6144 1 #define IDM_ABOUT 40001 diff --git a/src/WIN/win.c b/src/WIN/win.c index f368b56f4..1de2af41e 100644 --- a/src/WIN/win.c +++ b/src/WIN/win.c @@ -462,12 +462,12 @@ HMENU create_popup_menu(int part) void create_floppy_submenu(HMENU m, int id) { - AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_NEW | id, win_language_get_string_from_id(2211)); + AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_NEW | id, win_language_get_string_from_id(IDS_2161)); AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING | id, win_language_get_string_from_id(2212)); - AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING_WP | id, win_language_get_string_from_id(2213)); + AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING | id, win_language_get_string_from_id(IDS_2162)); + AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING_WP | id, win_language_get_string_from_id(IDS_2163)); AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_FLOPPY_EJECT | id, win_language_get_string_from_id(2214)); + AppendMenu(m, MF_STRING, IDM_FLOPPY_EJECT | id, win_language_get_string_from_id(IDS_2164)); } void create_cdrom_submenu(HMENU m, int id) @@ -475,12 +475,12 @@ void create_cdrom_submenu(HMENU m, int id) int i = 0; WCHAR s[64]; - AppendMenu(m, MF_STRING, IDM_CDROM_MUTE | id, win_language_get_string_from_id(2215)); + AppendMenu(m, MF_STRING, IDM_CDROM_MUTE | id, win_language_get_string_from_id(IDS_2165)); AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_CDROM_EMPTY | id, win_language_get_string_from_id(2216)); - AppendMenu(m, MF_STRING, IDM_CDROM_RELOAD | id, win_language_get_string_from_id(2217)); + AppendMenu(m, MF_STRING, IDM_CDROM_EMPTY | id, win_language_get_string_from_id(IDS_2166)); + AppendMenu(m, MF_STRING, IDM_CDROM_RELOAD | id, win_language_get_string_from_id(IDS_2167)); AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_CDROM_IMAGE | id, win_language_get_string_from_id(2218)); + AppendMenu(m, MF_STRING, IDM_CDROM_IMAGE | id, win_language_get_string_from_id(IDS_2168)); if (host_cdrom_drive_available_num == 0) { @@ -536,13 +536,13 @@ check_menu_items: void create_removable_disk_submenu(HMENU m, int id) { - AppendMenu(m, MF_STRING, IDM_RDISK_EJECT | id, win_language_get_string_from_id(2216)); - AppendMenu(m, MF_STRING, IDM_RDISK_RELOAD | id, win_language_get_string_from_id(2217)); + AppendMenu(m, MF_STRING, IDM_RDISK_EJECT | id, win_language_get_string_from_id(IDS_2166)); + AppendMenu(m, MF_STRING, IDM_RDISK_RELOAD | id, win_language_get_string_from_id(IDS_2167)); AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_RDISK_SEND_CHANGE | id, win_language_get_string_from_id(2201)); + AppendMenu(m, MF_STRING, IDM_RDISK_SEND_CHANGE | id, win_language_get_string_from_id(IDS_2142)); AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE | id, win_language_get_string_from_id(2218)); - AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE_WP | id, win_language_get_string_from_id(2220)); + AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE | id, win_language_get_string_from_id(IDS_2168)); + AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE_WP | id, win_language_get_string_from_id(IDS_2169)); } void get_executable_name(wchar_t *s, int size) @@ -789,7 +789,7 @@ void create_floppy_tip(int part) mbstowcs(wtext, fdd_getname(fdd_get_type(drive)), strlen(fdd_getname(fdd_get_type(drive))) + 1); if (wcslen(discfns[drive]) == 0) { - _swprintf(tempTip, win_language_get_string_from_id(2179), drive + 1, wtext, win_language_get_string_from_id(2185)); + _swprintf(tempTip, win_language_get_string_from_id(IDS_2158), drive + 1, wtext, win_language_get_string_from_id(IDS_2057)); } else { @@ -809,27 +809,36 @@ void create_cdrom_tip(int part) WCHAR wtext[512]; WCHAR tempTip[512]; + WCHAR *szText; + int id; + int drive = sb_part_meanings[part] & 0xf; + int bus = cdrom_drives[drive].bus_type; + + id = IDS_4352 + (bus - 1); + + szText = (WCHAR *) win_language_get_string_from_id(id); + if (cdrom_drives[drive].host_drive == 200) { if (wcslen(cdrom_image[drive].image_path) == 0) { - _swprintf(tempTip, win_language_get_string_from_id(2180), drive + 1, win_language_get_string_from_id(2185)); + _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, win_language_get_string_from_id(IDS_2057)); } else { - _swprintf(tempTip, win_language_get_string_from_id(2180), drive + 1, cdrom_image[drive].image_path); + _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, cdrom_image[drive].image_path); } } - else if (cdrom_drives[drive].host_drive < 0x41) + else if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { - _swprintf(tempTip, win_language_get_string_from_id(2180), drive + 1, win_language_get_string_from_id(2185)); + _swprintf(wtext, win_language_get_string_from_id(IDS_2058), cdrom_drives[drive].host_drive & ~0x20); + _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, wtext); } else { - _swprintf(wtext, win_language_get_string_from_id(2186), cdrom_drives[drive].host_drive & ~0x20); - _swprintf(tempTip, win_language_get_string_from_id(2180), drive + 1, wtext); + _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, win_language_get_string_from_id(IDS_2057)); } if (sbTips[part] != NULL) @@ -848,11 +857,11 @@ void create_removable_hd_tip(int part) if (wcslen(hdc[drive].fn) == 0) { - _swprintf(tempTip, win_language_get_string_from_id(2198), drive, win_language_get_string_from_id(2185)); + _swprintf(tempTip, win_language_get_string_from_id(IDS_4115), drive, win_language_get_string_from_id(IDS_2057)); } else { - _swprintf(tempTip, win_language_get_string_from_id(2198), drive, hdc[drive].fn); + _swprintf(tempTip, win_language_get_string_from_id(IDS_4115), drive, hdc[drive].fn); } if (sbTips[part] != NULL) @@ -865,41 +874,24 @@ void create_removable_hd_tip(int part) void create_hd_tip(int part) { + WCHAR tempTip[512]; WCHAR *szText; - int id = 2181; + int id; int bus = sb_part_meanings[part] & 0xf; - switch(bus) - { - case HDD_BUS_MFM: - id = 2181; - break; - case HDD_BUS_RLL: - id = 2207; - break; - case HDD_BUS_XTIDE: - id = 2208; - break; - case HDD_BUS_IDE_PIO_ONLY: - id = 2182; - break; - case HDD_BUS_IDE_PIO_AND_DMA: - id = 2183; - break; - case HDD_BUS_SCSI: - id = 2184; - break; - } + id = IDS_4352 + (bus - 1); szText = (WCHAR *) win_language_get_string_from_id(id); + _swprintf(tempTip, win_language_get_string_from_id(IDS_4096), szText); + if (sbTips[part] != NULL) { free(sbTips[part]); } - sbTips[part] = (WCHAR *) malloc((wcslen(szText) << 1) + 2); - wcscpy(sbTips[part], szText); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); } void update_tip(int meaning) @@ -1920,7 +1912,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM if (video_fullscreen_first) { video_fullscreen_first = 0; - msgbox_info(ghwnd, IDS_2193); + msgbox_info(ghwnd, IDS_2074); } startblit(); @@ -2068,7 +2060,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM case IDM_CONFIG_LOAD: pause = 1; - if (!file_dlg_st(hwnd, IDS_2174, "", 0)) + if (!file_dlg_st(hwnd, IDS_2160, "", 0)) { if (msgbox_reset_yn(ghwnd) == IDYES) { @@ -2133,7 +2125,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM case IDM_CONFIG_SAVE: pause = 1; - if (!file_dlg_st(hwnd, IDS_2174, "", 1)) + if (!file_dlg_st(hwnd, IDS_2160, "", 1)) { config_save(wopenfilestring); } @@ -2369,7 +2361,7 @@ LRESULT CALLBACK StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPAR break; } - ret = file_dlg_w_st(hwnd, IDS_2173, discfns[id], 0); + ret = file_dlg_w_st(hwnd, IDS_2159, discfns[id], 0); if (!ret) { disc_close(id); @@ -2425,7 +2417,7 @@ LRESULT CALLBACK StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPAR break; } - if (!file_dlg_w_st(hwnd, IDS_2175, cdrom_image[id].image_path, 0)) + if (!file_dlg_w_st(hwnd, IDS_2151, cdrom_image[id].image_path, 0)) { cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; wcscpy(temp_image_path, wopenfilestring); @@ -2514,7 +2506,7 @@ LRESULT CALLBACK StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPAR case IDM_RDISK_IMAGE: case IDM_RDISK_IMAGE_WP: id = item_params & 0x001f; - ret = file_dlg_w_st(hwnd, IDS_2172, hdc[id].fn, id); + ret = file_dlg_w_st(hwnd, IDS_4106, hdc[id].fn, id); if (!ret) { removable_disk_unload(id); diff --git a/src/WIN/win_ddraw_screenshot.cc b/src/WIN/win_ddraw_screenshot.cc index b98a207d1..292c0eb93 100644 --- a/src/WIN/win_ddraw_screenshot.cc +++ b/src/WIN/win_ddraw_screenshot.cc @@ -118,7 +118,7 @@ void SaveBitmap(wchar_t *szFilename,HBITMAP hBitmap) if((fp = _wfopen(szFilename,L"wb"))==NULL) { - _swprintf(szMessage, win_language_get_string_from_id(2194), szFilename); + _swprintf(szMessage, win_language_get_string_from_id(IDS_2073), szFilename); msgbox_error_wstr(ghwnd, szMessage); break; } diff --git a/src/WIN/win_language.c b/src/WIN/win_language.c index 84eabd1b7..e2bf2b24a 100644 --- a/src/WIN/win_language.c +++ b/src/WIN/win_language.c @@ -37,7 +37,20 @@ LCID dwLanguage; uint32_t dwLangID, dwSubLangID; -WCHAR lpResourceString[STRINGS_NUM][512]; +typedef struct +{ + WCHAR lpString[512]; +} resource_string_t; + +resource_string_t *lpResourceString2048; +resource_string_t *lpResourceString3072; +resource_string_t *lpResourceString4096; +resource_string_t *lpResourceString4352; +resource_string_t *lpResourceString4608; +resource_string_t *lpResourceString5120; +resource_string_t *lpResourceString5376; +resource_string_t *lpResourceString5632; +resource_string_t *lpResourceString6144; char openfilestring[260]; WCHAR wopenfilestring[260]; @@ -51,15 +64,65 @@ void win_language_load_common_strings() { int i = 0; - for (i = 0; i < STRINGS_NUM; i++) + lpResourceString2048 = (resource_string_t *) malloc(STRINGS_NUM_2048 * sizeof(resource_string_t)); + lpResourceString3072 = (resource_string_t *) malloc(STRINGS_NUM_3072 * sizeof(resource_string_t)); + lpResourceString4096 = (resource_string_t *) malloc(STRINGS_NUM_4096 * sizeof(resource_string_t)); + lpResourceString4352 = (resource_string_t *) malloc(STRINGS_NUM_4352 * sizeof(resource_string_t)); + lpResourceString4608 = (resource_string_t *) malloc(STRINGS_NUM_4608 * sizeof(resource_string_t)); + lpResourceString5120 = (resource_string_t *) malloc(STRINGS_NUM_5120 * sizeof(resource_string_t)); + lpResourceString5376 = (resource_string_t *) malloc(STRINGS_NUM_5376 * sizeof(resource_string_t)); + lpResourceString5632 = (resource_string_t *) malloc(STRINGS_NUM_5632 * sizeof(resource_string_t)); + lpResourceString6144 = (resource_string_t *) malloc(STRINGS_NUM_6144 * sizeof(resource_string_t)); + + for (i = 0; i < STRINGS_NUM_2048; i++) { - LoadString(hinstance, 2048 + i, lpResourceString[i], 512); + LoadString(hinstance, 2048 + i, lpResourceString2048[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_3072; i++) + { + LoadString(hinstance, 3072 + i, lpResourceString3072[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_4096; i++) + { + LoadString(hinstance, 4096 + i, lpResourceString4096[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_4352; i++) + { + LoadString(hinstance, 4352 + i, lpResourceString4352[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_4608; i++) + { + LoadString(hinstance, 4608 + i, lpResourceString4608[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_5120; i++) + { + LoadString(hinstance, 5120 + i, lpResourceString5120[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_5376; i++) + { + LoadString(hinstance, 5376 + i, lpResourceString5376[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_5632; i++) + { + LoadString(hinstance, 5632 + i, lpResourceString5632[i].lpString, 512); + } + + for (i = 0; i < STRINGS_NUM_6144; i++) + { + LoadString(hinstance, 6144 + i, lpResourceString6144[i].lpString, 512); } } LPTSTR win_language_get_settings_category(int i) { - return lpResourceString[17 + i]; + return lpResourceString2048[17 + i].lpString; } void win_language_update() @@ -81,7 +144,42 @@ void win_language_check() LPTSTR win_language_get_string_from_id(int i) { - return lpResourceString[i - 2048]; + if ((i >= 2048) && (i <= 3071)) + { + return lpResourceString2048[i - 2048].lpString; + } + else if ((i >= 3072) && (i <= 4095)) + { + return lpResourceString3072[i - 3072].lpString; + } + else if ((i >= 4096) && (i <= 4351)) + { + return lpResourceString4096[i - 4096].lpString; + } + else if ((i >= 4352) && (i <= 4607)) + { + return lpResourceString4352[i - 4352].lpString; + } + else if ((i >= 4608) && (i <= 5119)) + { + return lpResourceString4608[i - 4608].lpString; + } + else if ((i >= 5120) && (i <= 5375)) + { + return lpResourceString5120[i - 5120].lpString; + } + else if ((i >= 5376) && (i <= 5631)) + { + return lpResourceString5376[i - 5376].lpString; + } + else if ((i >= 5632) && (i <= 6143)) + { + return lpResourceString5632[i - 5632].lpString; + } + else + { + return lpResourceString6144[i - 6144].lpString; + } } wchar_t *plat_get_string_from_id(int i) @@ -91,37 +189,37 @@ wchar_t *plat_get_string_from_id(int i) LPTSTR win_language_get_string_from_string(char *str) { - return lpResourceString[atoi(str) - 2048]; + return win_language_get_string_from_id(atoi(str)); } int msgbox_reset(HWND hwndParent) { - return MessageBox(hwndParent, lpResourceString[3], lpResourceString[0], MB_YESNOCANCEL | MB_ICONQUESTION); + return MessageBox(hwndParent, lpResourceString2048[3].lpString, lpResourceString2048[0].lpString, MB_YESNOCANCEL | MB_ICONQUESTION); } int msgbox_reset_yn(HWND hwndParent) { - return MessageBox(hwndParent, lpResourceString[3], lpResourceString[0], MB_YESNO | MB_ICONQUESTION); + return MessageBox(hwndParent, lpResourceString2048[3].lpString, lpResourceString2048[0].lpString, MB_YESNO | MB_ICONQUESTION); } int msgbox_question(HWND hwndParent, int i) { - return MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString[0], MB_YESNO | MB_ICONQUESTION); + return MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[0].lpString, MB_YESNO | MB_ICONQUESTION); } void msgbox_info(HWND hwndParent, int i) { - MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString[0], MB_OK | MB_ICONINFORMATION); + MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[0].lpString, MB_OK | MB_ICONINFORMATION); } void msgbox_info_wstr(HWND hwndParent, WCHAR *wstr) { - MessageBox(hwndParent, wstr, lpResourceString[0], MB_OK | MB_ICONINFORMATION); + MessageBox(hwndParent, wstr, lpResourceString2048[0].lpString, MB_OK | MB_ICONINFORMATION); } void msgbox_error(HWND hwndParent, int i) { - MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString[1], MB_OK | MB_ICONWARNING); + MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[1].lpString, MB_OK | MB_ICONWARNING); } void plat_msgbox_error(int i) @@ -131,12 +229,12 @@ void plat_msgbox_error(int i) void msgbox_error_wstr(HWND hwndParent, WCHAR *wstr) { - MessageBox(hwndParent, wstr, lpResourceString[1], MB_OK | MB_ICONWARNING); + MessageBox(hwndParent, wstr, lpResourceString2048[1].lpString, MB_OK | MB_ICONWARNING); } void msgbox_critical(HWND hwndParent, int i) { - MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString[2], MB_OK | MB_ICONERROR); + MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[2].lpString, MB_OK | MB_ICONERROR); } void msgbox_fatal(HWND hwndParent, char *string) @@ -146,7 +244,7 @@ void msgbox_fatal(HWND hwndParent, char *string) mbstowcs(lptsTemp, string, strlen(string) + 1); - MessageBox(hwndParent, lptsTemp, lpResourceString[2], MB_OK | MB_ICONERROR); + MessageBox(hwndParent, lptsTemp, lpResourceString2048[2].lpString, MB_OK | MB_ICONERROR); free(lptsTemp); } diff --git a/src/WIN/win_settings.c b/src/WIN/win_settings.c index eb2866f7c..32c7016b4 100644 --- a/src/WIN/win_settings.c +++ b/src/WIN/win_settings.c @@ -624,7 +624,7 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w deviceconfig_open(hdlg, (void *)model_getdevice(temp_model)); break; case IDC_BUTTON_NVR_PATH: - p = BrowseFolder(temp_nvr_path, win_language_get_string_from_id(IDS_2225)); + p = BrowseFolder(temp_nvr_path, win_language_get_string_from_id(IDS_2056)); if (wcscmp(p, L"")) { memset(temp_nvr_path, 0, sizeof(temp_nvr_path)); @@ -900,40 +900,7 @@ static BOOL CALLBACK win_settings_input_proc(HWND hdlg, UINT message, WPARAM wPa if (mouse_valid(type, temp_model)) { - switch(c) - { - case MOUSE_TYPE_NONE: - str_id = IDS_2151; - break; - case MOUSE_TYPE_SERIAL: - default: - str_id = IDS_2139; - break; - case MOUSE_TYPE_PS2: - str_id = IDS_2141; - break; - case MOUSE_TYPE_PS2_MS: - str_id = IDS_2142; - break; - case MOUSE_TYPE_BUS: - str_id = IDS_2143; - break; - case MOUSE_TYPE_AMSTRAD: - str_id = IDS_2162; - break; - case MOUSE_TYPE_OLIM24: - str_id = IDS_2177; - break; - case MOUSE_TYPE_MSYSTEMS: - str_id = IDS_2140; - break; - case MOUSE_TYPE_LOGITECH: - str_id = IDS_2224; - break; - case MOUSE_TYPE_GENIUS: - str_id = IDS_2161; - break; - } + str_id = IDS_3072 + c; SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(str_id)); @@ -1498,7 +1465,7 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR recalc_hdd_list(hdlg, temp_model, 0); h=GetDlgItem(hdlg, IDC_COMBO_IDE_TER); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2151)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_5376)); for (c = 0; c < 11; c++) { @@ -1516,7 +1483,7 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR } h=GetDlgItem(hdlg, IDC_COMBO_IDE_QUA); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2151)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_5376)); for (c = 0; c < 11; c++) { @@ -1921,41 +1888,36 @@ static void add_locations(HWND hdlg) lptsTemp = (LPTSTR) malloc(512); h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - for (i = 0; i < 4; i++) + for (i = 0; i < 7; i++) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2165 + i)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_4352 + i)); } - for (i = 0; i < 2; i++) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2209 + i)); - } - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2202)); h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2169), i >> 1, i & 1); + wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4097), i >> 1, i & 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2088), i); + wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2088), i); + wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2169), i >> 1, i & 1); + wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4097), i >> 1, i & 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } @@ -2010,16 +1972,6 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg) EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.mfm_channel : temp_hdc[hdlv_current_sel].mfm_channel, 0); break; - case HDD_BUS_RLL: /* RLL */ - h = GetDlgItem(hdlg, IDT_1722); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.rll_channel : temp_hdc[hdlv_current_sel].rll_channel, 0); - break; case HDD_BUS_XTIDE: /* XT IDE */ h = GetDlgItem(hdlg, IDT_1722); ShowWindow(h, SW_SHOW); @@ -2030,6 +1982,16 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg) EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.xtide_channel : temp_hdc[hdlv_current_sel].xtide_channel, 0); break; + case HDD_BUS_RLL: /* RLL */ + h = GetDlgItem(hdlg, IDT_1722); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.rll_channel : temp_hdc[hdlv_current_sel].rll_channel, 0); + break; case HDD_BUS_IDE_PIO_ONLY: /* IDE (PIO-only) */ case HDD_BUS_IDE_PIO_AND_DMA: /* IDE (PIO and DMA) */ h = GetDlgItem(hdlg, IDT_1722); @@ -2197,25 +2159,25 @@ static void win_settings_hard_disks_update_item(HWND hwndList, int i, int column switch(temp_hdc[i].bus) { case HDD_BUS_MFM: - wsprintf(szText, win_language_get_string_from_id(2156), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1); - break; - case HDD_BUS_RLL: - wsprintf(szText, win_language_get_string_from_id(2205), temp_hdc[i].rll_channel >> 1, temp_hdc[i].rll_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1); break; case HDD_BUS_XTIDE: - wsprintf(szText, win_language_get_string_from_id(2206), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1); + break; + case HDD_BUS_RLL: + wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdc[i].rll_channel >> 1, temp_hdc[i].rll_channel & 1); break; case HDD_BUS_IDE_PIO_ONLY: - wsprintf(szText, win_language_get_string_from_id(2195), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); break; case HDD_BUS_IDE_PIO_AND_DMA: - wsprintf(szText, win_language_get_string_from_id(2157), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); break; case HDD_BUS_SCSI: - wsprintf(szText, win_language_get_string_from_id(2158), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); break; case HDD_BUS_SCSI_REMOVABLE: - wsprintf(szText, win_language_get_string_from_id(2203), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); break; } lvI.pszText = szText; @@ -2228,25 +2190,25 @@ static void win_settings_hard_disks_update_item(HWND hwndList, int i, int column } else if (column == 2) { - wsprintf(szText, win_language_get_string_from_id(2088), temp_hdc[i].tracks); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].tracks); lvI.pszText = szText; lvI.iImage = 0; } else if (column == 3) { - wsprintf(szText, win_language_get_string_from_id(2088), temp_hdc[i].hpc); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].hpc); lvI.pszText = szText; lvI.iImage = 0; } else if (column == 4) { - wsprintf(szText, win_language_get_string_from_id(2088), temp_hdc[i].spt); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].spt); lvI.pszText = szText; lvI.iImage = 0; } else if (column == 5) { - wsprintf(szText, win_language_get_string_from_id(2088), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11); lvI.pszText = szText; lvI.iImage = 0; } @@ -2281,25 +2243,25 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) switch(temp_hdc[i].bus) { case HDD_BUS_MFM: - wsprintf(szText, win_language_get_string_from_id(2156), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1); - break; - case HDD_BUS_RLL: - wsprintf(szText, win_language_get_string_from_id(2205), temp_hdc[i].rll_channel >> 1, temp_hdc[i].rll_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1); break; case HDD_BUS_XTIDE: - wsprintf(szText, win_language_get_string_from_id(2206), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1); + break; + case HDD_BUS_RLL: + wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdc[i].rll_channel >> 1, temp_hdc[i].rll_channel & 1); break; case HDD_BUS_IDE_PIO_ONLY: - wsprintf(szText, win_language_get_string_from_id(2195), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); break; case HDD_BUS_IDE_PIO_AND_DMA: - wsprintf(szText, win_language_get_string_from_id(2157), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); break; case HDD_BUS_SCSI: - wsprintf(szText, win_language_get_string_from_id(2158), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); break; case HDD_BUS_SCSI_REMOVABLE: - wsprintf(szText, win_language_get_string_from_id(2203), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); break; } lvI.pszText = szText; @@ -2322,7 +2284,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 2; - wsprintf(szText, win_language_get_string_from_id(2088), temp_hdc[i].tracks); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].tracks); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2333,7 +2295,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 3; - wsprintf(szText, win_language_get_string_from_id(2088), temp_hdc[i].hpc); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].hpc); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2344,7 +2306,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 4; - wsprintf(szText, win_language_get_string_from_id(2088), temp_hdc[i].spt); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].spt); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2355,7 +2317,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 5; - wsprintf(szText, win_language_get_string_from_id(2088), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11); + wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2454,7 +2416,7 @@ static void set_edit_box_contents(HWND hdlg, int id, uint64_t val) WCHAR szText[256]; h = GetDlgItem(hdlg, id); - wsprintf(szText, win_language_get_string_from_id(2160), val); + wsprintf(szText, win_language_get_string_from_id(IDS_2156), val); SendMessage(h, WM_SETTEXT, (WPARAM) wcslen(szText), (LPARAM) szText); } @@ -2488,15 +2450,15 @@ static int hdconf_initialize_hdt_combo(HWND hdlg) { temp_size = hdt[i][0] * hdt[i][1] * hdt[i][2]; size_mb = temp_size >> 11; - wsprintf(szText, win_language_get_string_from_id(2171), size_mb, hdt[i][0], hdt[i][1], hdt[i][2]); + wsprintf(szText, win_language_get_string_from_id(IDS_2157), size_mb, hdt[i][0], hdt[i][1], hdt[i][2]); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); if ((tracks == hdt[i][0]) && (hpc == hdt[i][1]) && (spt == hdt[i][2])) { selection = i; } } - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2170)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2187)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_4100)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_4101)); SendMessage(h, CB_SETCURSEL, selection, 0); return selection; } @@ -2555,7 +2517,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W hdc_ptr = &(temp_hdc[next_free_id]); } - SetWindowText(hdlg, win_language_get_string_from_id((existing & 1) ? 2197 : 2196)); + SetWindowText(hdlg, win_language_get_string_from_id((existing & 1) ? IDS_4103 : IDS_4102)); no_update = 1; spt = (existing & 1) ? 0 : 17; @@ -2656,7 +2618,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W if ((wcslen(hd_file_name) == 0) && (hdc_ptr->bus != HDD_BUS_SCSI_REMOVABLE)) { hdc_ptr->bus = HDD_BUS_DISABLED; - msgbox_error(hwndParentDialog, IDS_2056); + msgbox_error(hwndParentDialog, IDS_4112); return TRUE; } else if ((wcslen(hd_file_name) == 0) && (hdc_ptr->bus == HDD_BUS_SCSI_REMOVABLE)) @@ -2728,7 +2690,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W if (size >= 0x100000000ll) { fclose(f); - msgbox_error(hwndParentDialog, IDS_2058); + msgbox_error(hwndParentDialog, IDS_4104); return TRUE; } @@ -2751,7 +2713,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W if (size > 0xffffffffffffffffll) { fclose(f); - msgbox_error(hwndParentDialog, IDS_2163); + msgbox_error(hwndParentDialog, IDS_4105); return TRUE; } @@ -2791,7 +2753,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W } fclose(f); - msgbox_info(hwndParentDialog, IDS_2059); + msgbox_info(hwndParentDialog, IDS_4113); } hd_add_ok_common: @@ -2809,7 +2771,7 @@ hd_add_ok_common: return TRUE; case IDC_CFILE: - if (!file_dlg_w(hdlg, win_language_get_string_from_id(2172), L"", !(existing & 1))) + if (!file_dlg_w(hdlg, win_language_get_string_from_id(IDS_4106), L"", !(existing & 1))) { if (!(existing & 1)) { @@ -2817,7 +2779,7 @@ hd_add_ok_common: if (f != NULL) { fclose(f); - if (msgbox_question(ghwnd, IDS_2178) != IDYES) + if (msgbox_question(ghwnd, IDS_4111) != IDYES) { return FALSE; } @@ -2828,7 +2790,7 @@ hd_add_ok_common: if (f == NULL) { hdd_add_file_open_error: - msgbox_error(hwndParentDialog, (existing & 1) ? 2060 : 2057); + msgbox_error(hwndParentDialog, (existing & 1) ? IDS_4107 : IDS_4108); return TRUE; } if (existing & 1) @@ -2839,7 +2801,7 @@ hdd_add_file_open_error: fread(§or_size, 1, 4, f); if (sector_size != 512) { - msgbox_error(hwndParentDialog, IDS_2061); + msgbox_error(hwndParentDialog, IDS_4109); fclose(f); return TRUE; } @@ -3471,42 +3433,12 @@ int cdlv_current_sel; static int combo_id_to_string_id(int combo_id) { - switch (combo_id) - { - case CDROM_BUS_DISABLED: /* Disabled */ - default: - return 2151; - break; - case CDROM_BUS_ATAPI_PIO_ONLY: /* Atapi (PIO-only) */ - return 2189; - break; - case CDROM_BUS_ATAPI_PIO_AND_DMA: /* Atapi (PIA and DMA) */ - return 2190; - break; - case CDROM_BUS_SCSI: /* SCSI */ - return 2210; - break; - } + return IDS_5376 + combo_id; } static int combo_id_to_format_string_id(int combo_id) { - switch (combo_id) - { - case CDROM_BUS_DISABLED: /* Disabled */ - default: - return 2151; - break; - case CDROM_BUS_ATAPI_PIO_ONLY: /* Atapi (PIO-only) */ - return 2191; - break; - case CDROM_BUS_ATAPI_PIO_AND_DMA: /* Atapi (PIA and DMA) */ - return 2192; - break; - case CDROM_BUS_SCSI: /* SCSI */ - return 2158; - break; - } + return IDS_5632 + combo_id; } static BOOL win_settings_floppy_drives_image_list_init(HWND hwndList) @@ -3583,7 +3515,7 @@ static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) } else { - lvI.pszText = win_language_get_string_from_id(2151); + lvI.pszText = win_language_get_string_from_id(IDS_5376); } lvI.iItem = i; lvI.iImage = temp_fdd_types[i]; @@ -3592,7 +3524,7 @@ static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) return FALSE; lvI.iSubItem = 1; - lvI.pszText = win_language_get_string_from_id(temp_fdd_turbo[i] ? 2222 : 2223); + lvI.pszText = win_language_get_string_from_id(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); lvI.iItem = i; lvI.iImage = 0; @@ -3659,7 +3591,7 @@ static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.iSubItem = 0; - lvc.pszText = win_language_get_string_from_id(2188); + lvc.pszText = win_language_get_string_from_id(IDS_2143); lvc.cx = 292; lvc.fmt = LVCFMT_LEFT; @@ -3670,7 +3602,7 @@ static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) } lvc.iSubItem = 1; - lvc.pszText = win_language_get_string_from_id(2221); + lvc.pszText = win_language_get_string_from_id(IDS_2059); lvc.cx = 100; lvc.fmt = LVCFMT_LEFT; @@ -3761,7 +3693,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) } else { - lvI.pszText = win_language_get_string_from_id(2151); + lvI.pszText = win_language_get_string_from_id(IDS_5376); } lvI.iImage = temp_fdd_types[i]; @@ -3771,7 +3703,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) } lvI.iSubItem = 1; - lvI.pszText = win_language_get_string_from_id(temp_fdd_turbo[i] ? 2222 : 2223); + lvI.pszText = win_language_get_string_from_id(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); lvI.iItem = i; lvI.iImage = 0; @@ -3953,7 +3885,7 @@ static BOOL CALLBACK win_settings_removable_devices_proc(HWND hdlg, UINT message { if (i == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2151)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_5376)); } else { diff --git a/src/config.c b/src/config.c index 2ebc6d3da..d7e62004f 100644 --- a/src/config.c +++ b/src/config.c @@ -1058,11 +1058,11 @@ static void loadconfig_network(void) { if ((network_ndev == 1) && strcmp(network_pcap, "none")) { - msgbox_error(ghwnd, IDS_2107); + msgbox_error(ghwnd, IDS_2140); } else if (network_dev_to_id(p) == -1) { - msgbox_error(ghwnd, IDS_2200); + msgbox_error(ghwnd, IDS_2141); } strcpy(network_pcap, "none"); @@ -1220,14 +1220,14 @@ static int config_string_to_bus(char *str, int cdrom) if (!strcmp(str, "usb")) { - msgbox_error(ghwnd, IDS_2199); + msgbox_error(ghwnd, IDS_4110); return 0; } return 0; no_mfm_cdrom: - msgbox_error(ghwnd, IDS_2095); + msgbox_error(ghwnd, IDS_4114); return 0; } diff --git a/src/mouse.c b/src/mouse.c index 9169a4fa9..123b88d35 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -35,16 +35,17 @@ static mouse_t mouse_none = { static mouse_t *mouse_list[] = { &mouse_none, - &mouse_serial_microsoft, /* 1 Microsoft Serial Mouse */ - &mouse_ps2_2_button, /* 2 PS/2 Mouse 2-button */ - &mouse_intellimouse, /* 3 PS/2 Intellimouse 3-button */ - &mouse_bus, /* 4 Logitech Bus Mouse 2-button */ - &mouse_amstrad, /* 5 Amstrad PC System Mouse */ - &mouse_olim24, /* 6 Olivetti M24 System Mouse */ - &mouse_msystems, /* 7 Mouse Systems */ - &mouse_serial_logitech, /* 1 Logitech 3-button Serial Mouse */ + &mouse_bus, /* 1 Logitech Bus Mouse 2-button */ + &mouse_msystems, /* 2 Mouse Systems */ + &mouse_serial_microsoft, /* 3 Microsoft Serial Mouse */ + &mouse_serial_logitech, /* 4 Logitech 3-button Serial Mouse */ + &mouse_serial_mswheel, /* 5 Microsoft Serial Wheel Mouse */ + &mouse_ps2_2_button, /* 6 PS/2 Mouse 2-button */ + &mouse_intellimouse, /* 7 PS/2 Intellimouse 3-button */ + &mouse_amstrad, /* 8 Amstrad PC System Mouse */ + &mouse_olim24, /* 9 Olivetti M24 System Mouse */ #if 0 - &mouse_genius, /* 8 Genius Bus Mouse */ + &mouse_genius, /* 10 Genius Bus Mouse */ #endif NULL }; diff --git a/src/mouse.h b/src/mouse.h index 21e1ff983..8eb2655cf 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -20,16 +20,19 @@ # define EMU_MOUSE_H -#define MOUSE_TYPE_NONE 0 -#define MOUSE_TYPE_SERIAL 1 /* Serial Mouse */ -#define MOUSE_TYPE_PS2 2 /* IBM PS/2 series Bus Mouse */ -#define MOUSE_TYPE_PS2_MS 3 /* Microsoft Intellimouse PS/2 */ -#define MOUSE_TYPE_BUS 4 /* Logitech/ATI Bus Mouse */ -#define MOUSE_TYPE_AMSTRAD 5 /* Amstrad PC system mouse */ -#define MOUSE_TYPE_OLIM24 6 /* Olivetti M24 system mouse */ -#define MOUSE_TYPE_MSYSTEMS 7 /* Mouse Systems mouse */ -#define MOUSE_TYPE_LOGITECH 8 /* Logitech Serial Mouse */ -#define MOUSE_TYPE_GENIUS 9 /* Genius Bus Mouse */ +#define MOUSE_TYPE_NONE 0 +#if 0 +#define MOUSE_TYPE_GENIUS 10 /* Genius Bus Mouse */ +#endif +#define MOUSE_TYPE_BUS 1 /* Logitech/ATI Bus Mouse */ +#define MOUSE_TYPE_MSYSTEMS 2 /* Mouse Systems mouse */ +#define MOUSE_TYPE_SERIAL 3 /* Serial Mouse */ +#define MOUSE_TYPE_LOGITECH 4 /* Logitech Serial Mouse */ +#define MOUSE_TYPE_MSWHEEL 5 /* Serial Wheel Mouse */ +#define MOUSE_TYPE_PS2 6 /* IBM PS/2 series Bus Mouse */ +#define MOUSE_TYPE_PS2_MS 7 /* Microsoft Intellimouse PS/2 */ +#define MOUSE_TYPE_AMSTRAD 8 /* Amstrad PC system mouse */ +#define MOUSE_TYPE_OLIM24 9 /* Olivetti M24 system mouse */ #define MOUSE_TYPE_MASK 0x0f #define MOUSE_TYPE_3BUTTON (1<<7) /* device has 3+ buttons */ diff --git a/src/mouse_serial.c b/src/mouse_serial.c index d50b71d2e..fa7e709c6 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -273,9 +273,18 @@ uint8_t mouse_serial_poll(int x, int y, int z, int b, void *p) serial_write_fifo(mouse->serial, mousedat[0]); serial_write_fifo(mouse->serial, mousedat[1]); serial_write_fifo(mouse->serial, mousedat[2]); - if ((b&0x04) && mouse->type) + if (mouse->type == 2) { - serial_write_fifo(mouse->serial, 0x20); + if (b&0x04) + { + serial_write_fifo(mouse->serial, 0x20); + } + } + else if (mouse->type == 3) + { + mousedat[3] = z & 0xf; + if (b&4) mousedat[3] |= 0x10; + serial_write_fifo(mouse->serial, mousedat[3]); } } @@ -339,13 +348,23 @@ void mousecallback(void *p) if (mouse->mousepos == -1) { mouse->mousepos = 0; - if (mouse->type < 2) + switch(mouse->type) { - serial_write_fifo(mouse->serial, 'M'); - if (mouse->type == 1) - { + case 0: + serial_write_fifo(mouse->serial, 'H'); + break; + case 1: + default: + serial_write_fifo(mouse->serial, 'M'); + break; + case 2: + serial_write_fifo(mouse->serial, 'M'); serial_write_fifo(mouse->serial, '3'); - } + break; + case 3: + serial_write_fifo(mouse->serial, 'M'); + serial_write_fifo(mouse->serial, 'Z'); + break; } } } @@ -365,21 +384,26 @@ void *mouse_serial_common_init(int type) return mouse; } -void *mouse_serial_init() +void *mouse_serial_msystems_init() { return mouse_serial_common_init(0); } -void *mouse_serial_logitech_init() +void *mouse_serial_init() { return mouse_serial_common_init(1); } -void *mouse_serial_msystems_init() +void *mouse_serial_logitech_init() { return mouse_serial_common_init(2); } +void *mouse_serial_mswheel_init() +{ + return mouse_serial_common_init(3); +} + void mouse_serial_close(void *p) { mouse_serial_t *mouse = (mouse_serial_t *)p; @@ -389,6 +413,16 @@ void mouse_serial_close(void *p) serial1.rcr_callback = NULL; } +mouse_t mouse_msystems = +{ + "Mouse Systems Mouse (serial)", + "mssystems", + MOUSE_TYPE_MSYSTEMS | MOUSE_TYPE_3BUTTON, + mouse_serial_msystems_init, + mouse_serial_close, + mouse_serial_msystems_poll +}; + mouse_t mouse_serial_microsoft = { "Microsoft 2-button mouse (serial)", @@ -403,20 +437,20 @@ mouse_t mouse_serial_logitech = { "Logitech 3-button mouse (serial)", "lserial", - MOUSE_TYPE_SERIAL | MOUSE_TYPE_3BUTTON, + MOUSE_TYPE_LOGITECH | MOUSE_TYPE_3BUTTON, mouse_serial_logitech_init, mouse_serial_close, mouse_serial_poll }; -mouse_t mouse_msystems = +mouse_t mouse_serial_mswheel = { - "Mouse Systems Mouse (serial)", + "Microsoft wheel mouse (serial)", "mssystems", - MOUSE_TYPE_MSYSTEMS | MOUSE_TYPE_3BUTTON, - mouse_serial_msystems_init, + MOUSE_TYPE_MSWHEEL | MOUSE_TYPE_3BUTTON, + mouse_serial_mswheel_init, mouse_serial_close, - mouse_serial_msystems_poll + mouse_serial_poll }; diff --git a/src/mouse_serial.h b/src/mouse_serial.h index 27626c08c..f6c5a45d1 100644 --- a/src/mouse_serial.h +++ b/src/mouse_serial.h @@ -21,9 +21,10 @@ #define SERMOUSE_PORT 1 /* attach to Serial1 */ +extern mouse_t mouse_msystems; extern mouse_t mouse_serial_microsoft; extern mouse_t mouse_serial_logitech; -extern mouse_t mouse_msystems; +extern mouse_t mouse_serial_mswheel; #endif /*MOUSE_SERIAL_H*/ From 36fcf10388bea787f6a5c2a78bbbe889625fb809 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Jul 2017 15:21:17 +0200 Subject: [PATCH 24/82] REP instructions now correctly issue a Debug exception after every iteration, fixes NT 3.x on 386 CPU's; Fixed a string bug in the Settings dialog (Joysticks combo box). --- src/CPU/386_dynarec_ops.c | 2 ++ src/CPU/x86_ops_rep.h | 36 ++++++++++++++++++++++++++++++++++++ src/WIN/86Box.rc | 3 ++- src/WIN/win.c | 2 +- 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/CPU/386_dynarec_ops.c b/src/CPU/386_dynarec_ops.c index e0e018872..db6958e5a 100644 --- a/src/CPU/386_dynarec_ops.c +++ b/src/CPU/386_dynarec_ops.c @@ -17,6 +17,8 @@ #include "386_common.h" +extern int trap; + extern uint16_t *mod1add[2][8]; extern uint32_t *mod1seg[8]; diff --git a/src/CPU/x86_ops_rep.h b/src/CPU/x86_ops_rep.h index 140f60916..b26b3be3d 100644 --- a/src/CPU/x86_ops_rep.h +++ b/src/CPU/x86_ops_rep.h @@ -167,6 +167,9 @@ static int opREP_MOVSB_ ## size(uint32_t fetchdat) int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ uint8_t temp; \ @@ -199,6 +202,9 @@ static int opREP_MOVSW_ ## size(uint32_t fetchdat) int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ uint16_t temp; \ @@ -231,6 +237,9 @@ static int opREP_MOVSL_ ## size(uint32_t fetchdat) int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ uint32_t temp; \ @@ -265,6 +274,9 @@ static int opREP_STOSB_ ## size(uint32_t fetchdat) int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ @@ -292,6 +304,9 @@ static int opREP_STOSW_ ## size(uint32_t fetchdat) int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+1); \ @@ -319,6 +334,9 @@ static int opREP_STOSL_ ## size(uint32_t fetchdat) int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+3); \ @@ -347,6 +365,9 @@ static int opREP_LODSB_ ## size(uint32_t fetchdat) int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -373,6 +394,9 @@ static int opREP_LODSW_ ## size(uint32_t fetchdat) int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -399,6 +423,9 @@ static int opREP_LODSL_ ## size(uint32_t fetchdat) int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ while (CNT_REG > 0) \ { \ EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -510,6 +537,9 @@ static int opREP_SCASB_ ## size(uint32_t fetchdat) int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ tempz = FV; \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ @@ -540,6 +570,9 @@ static int opREP_SCASW_ ## size(uint32_t fetchdat) int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ tempz = FV; \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ @@ -570,6 +603,9 @@ static int opREP_SCASL_ ## size(uint32_t fetchdat) int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ \ + if (trap) \ + cycles_end = cycles+1; \ + \ tempz = FV; \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ diff --git a/src/WIN/86Box.rc b/src/WIN/86Box.rc index 991b8bfe5..ee54378a1 100644 --- a/src/WIN/86Box.rc +++ b/src/WIN/86Box.rc @@ -726,6 +726,7 @@ BEGIN IDS_2072 "Removable devices" IDS_2073 "Unable to create bitmap file: %s" IDS_2074 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" + IDS_2075 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" IDS_2076 "Host CD/DVD Drive (%c:)" IDS_2077 "Click to capture mouse" IDS_2078 "Press F12-F8 to release mouse" @@ -818,7 +819,7 @@ BEGIN IDS_2148 "CH Flightstick Pro" IDS_2149 "Microsoft SideWinder Pad" IDS_2150 "Thrustmaster Flight Control System" - IDS_2151 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" + IDS_2151 "Disabled" IDS_2152 "None" IDS_2153 "AT Fixed Disk Adapter" IDS_2154 "Internal IDE" diff --git a/src/WIN/win.c b/src/WIN/win.c index 1de2af41e..66c20625c 100644 --- a/src/WIN/win.c +++ b/src/WIN/win.c @@ -2417,7 +2417,7 @@ LRESULT CALLBACK StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPAR break; } - if (!file_dlg_w_st(hwnd, IDS_2151, cdrom_image[id].image_path, 0)) + if (!file_dlg_w_st(hwnd, IDS_2075, cdrom_image[id].image_path, 0)) { cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; wcscpy(temp_image_path, wopenfilestring); From abf5b44b084787a5ef739791a05dfe94614b26a9 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 24 Jul 2017 16:34:56 +0200 Subject: [PATCH 25/82] Added proper Bus Mouse emulation and introduced InPort Mouse emulation. --- src/WIN/86Box.rc | 17 +- src/WIN/resource.h | 3 +- src/mouse.c | 5 +- src/mouse.h | 3 +- src/mouse_bus.c | 771 ++++++++++++++++++++++----------------------- src/mouse_bus.h | 6 +- 6 files changed, 398 insertions(+), 407 deletions(-) diff --git a/src/WIN/86Box.rc b/src/WIN/86Box.rc index ee54378a1..04d628200 100644 --- a/src/WIN/86Box.rc +++ b/src/WIN/86Box.rc @@ -841,14 +841,15 @@ BEGIN IDS_3072 "None" IDS_3073 "[Bus] Bus mouse" - IDS_3074 "[Serial] Mouse Systems mouse" - IDS_3075 "[Serial] Microsoft 2-button mouse" - IDS_3076 "[Serial] Logitech 3-button mouse" - IDS_3077 "[Serial] Microsoft wheel mouse" - IDS_3078 "[PS/2] 2-button mouse" - IDS_3079 "[PS/2] Microsoft Intellimouse" - IDS_3080 "[Proprietary] Amstrad mouse" - IDS_3081 "[Proprietary] Olivetti M24 mouse" + IDS_3074 "[Bus] InPort mouse" + IDS_3075 "[Serial] Mouse Systems mouse" + IDS_3076 "[Serial] Microsoft 2-button mouse" + IDS_3077 "[Serial] Logitech 3-button mouse" + IDS_3078 "[Serial] Microsoft wheel mouse" + IDS_3079 "[PS/2] 2-button mouse" + IDS_3080 "[PS/2] Microsoft Intellimouse" + IDS_3081 "[Proprietary] Amstrad mouse" + IDS_3082 "[Proprietary] Olivetti M24 mouse" IDS_4096 "Hard disk (%s)" IDS_4097 "%01i:%01i" diff --git a/src/WIN/resource.h b/src/WIN/resource.h index 9fa250250..41206cb1f 100644 --- a/src/WIN/resource.h +++ b/src/WIN/resource.h @@ -330,6 +330,7 @@ #define IDS_3079 3079 #define IDS_3080 3080 #define IDS_3081 3081 +#define IDS_3082 3082 #define IDS_4096 4096 #define IDS_4097 4097 @@ -391,7 +392,7 @@ #define IDS_LANG_ENUS IDS_6144 #define STRINGS_NUM_2048 122 -#define STRINGS_NUM_3072 10 +#define STRINGS_NUM_3072 11 #define STRINGS_NUM_4096 20 #define STRINGS_NUM_4352 7 #define STRINGS_NUM_4608 7 diff --git a/src/mouse.c b/src/mouse.c index 123b88d35..1d23821b0 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -35,7 +35,7 @@ static mouse_t mouse_none = { static mouse_t *mouse_list[] = { &mouse_none, - &mouse_bus, /* 1 Logitech Bus Mouse 2-button */ + &mouse_bus, /* 1 Microsoft/Logitech Bus Mouse 2-button */ &mouse_msystems, /* 2 Mouse Systems */ &mouse_serial_microsoft, /* 3 Microsoft Serial Mouse */ &mouse_serial_logitech, /* 4 Logitech 3-button Serial Mouse */ @@ -44,8 +44,9 @@ static mouse_t *mouse_list[] = { &mouse_intellimouse, /* 7 PS/2 Intellimouse 3-button */ &mouse_amstrad, /* 8 Amstrad PC System Mouse */ &mouse_olim24, /* 9 Olivetti M24 System Mouse */ + &mouse_inport, /* 10 Microsoft InPort Mouse */ #if 0 - &mouse_genius, /* 10 Genius Bus Mouse */ + &mouse_genius, /* 11 Genius Bus Mouse */ #endif NULL }; diff --git a/src/mouse.h b/src/mouse.h index 8eb2655cf..daa0cddc3 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -22,7 +22,7 @@ #define MOUSE_TYPE_NONE 0 #if 0 -#define MOUSE_TYPE_GENIUS 10 /* Genius Bus Mouse */ +#define MOUSE_TYPE_GENIUS 11 /* Genius Bus Mouse */ #endif #define MOUSE_TYPE_BUS 1 /* Logitech/ATI Bus Mouse */ #define MOUSE_TYPE_MSYSTEMS 2 /* Mouse Systems mouse */ @@ -33,6 +33,7 @@ #define MOUSE_TYPE_PS2_MS 7 /* Microsoft Intellimouse PS/2 */ #define MOUSE_TYPE_AMSTRAD 8 /* Amstrad PC system mouse */ #define MOUSE_TYPE_OLIM24 9 /* Olivetti M24 system mouse */ +#define MOUSE_TYPE_INPORT 10 /* Microsoft InPort Mouse */ #define MOUSE_TYPE_MASK 0x0f #define MOUSE_TYPE_3BUTTON (1<<7) /* device has 3+ buttons */ diff --git a/src/mouse_bus.c b/src/mouse_bus.c index b8cec9f82..8205c37dc 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -42,452 +42,443 @@ #include "ibm.h" #include "io.h" #include "pic.h" +#include "timer.h" #include "mouse.h" #include "mouse_bus.h" #include "plat_mouse.h" +#define BUS_MOUSE_IRQ 5 +#define IRQ_MASK ((1<<5) >> BUS_MOUSE_IRQ) -#define ENABLE_3BTN 1 /* enable 3-button mode */ +// MS Inport Bus Mouse Adapter +#define INP_PORT_CONTROL 0x023C +#define INP_PORT_DATA 0x023D +#define INP_PORT_SIGNATURE 0x023E +#define INP_PORT_CONFIG 0x023F +#define INP_CTRL_READ_BUTTONS 0x00 +#define INP_CTRL_READ_X 0x01 +#define INP_CTRL_READ_Y 0x02 +#define INP_CTRL_COMMAND 0x07 +#define INP_CTRL_RAISE_IRQ 0x16 +#define INP_CTRL_RESET 0x80 -/* Register definitions for Logitech mode. */ -#define LTMOUSE_DATA 0 /* DATA register */ -#define LTMOUSE_MAGIC 1 /* signature magic register */ -# define MAGIC_BYTE1 0xa5 /* most drivers use this */ -# define MAGIC_BYTE2 0x5a /* some drivers use this */ -#define LTMOUSE_CTRL 2 /* CTRL register */ -# define CTRL_FREEZE 0x80 /* do not sample when set */ -# define CTRL_RD_Y_HI 0x60 /* plus FREEZE */ -# define CTRL_RD_Y_LO 0x40 /* plus FREEZE */ -# define CTRL_RD_X_HI 0x20 /* plus FREEZE */ -# define CTRL_RD_X_LO 0x00 /* plus FREEZE */ -# define CTRL_RD_MASK 0x60 -# define CTRL_IDIS 0x10 -# define CTRL_IENB 0x00 -# define CTRL_DFLT (CTRL_IDIS) -#define LTMOUSE_CONFIG 3 /* CONFIG register */ -# define CONFIG_DFLT 0x91 /* 8255 controller config */ +#define INP_HOLD_COUNTER (1 << 5) +#define INP_ENABLE_IRQ (1 << 0) -/* Register definitions for Microsoft mode. */ -#define MSMOUSE_CTRL 0 /* CTRL register */ -# define MSCTRL_RESET 0x80 -# define MSCTRL_MODE 0x07 -# define MSCTRL_RD_Y 0x02 -# define MSCTRL_RD_X 0x01 -# define MSCTRL_RD_BUT 0x00 -#define MSMOUSE_DATA 1 /* DATA register */ -# define MSDATA_BASE 0x10 -# define MSDATA_IRQ 0x01 -#define MSMOUSE_MAGIC 2 /* MAGIC register */ -# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */ -# define MAGIC_MSBYTE2 0xad -#define MSMOUSE_CONFIG 3 /* CONFIG register */ +// MS/Logictech Standard Bus Mouse Adapter +#define BUSM_PORT_DATA 0x023C +#define BUSM_PORT_SIGNATURE 0x023D +#define BUSM_PORT_CONTROL 0x023E +#define BUSM_PORT_CONFIG 0x023F + +#define HOLD_COUNTER (1 << 7) +#define READ_X (0 << 6) +#define READ_Y (1 << 6) +#define READ_LOW (0 << 5) +#define READ_HIGH (1 << 5) +#define DISABLE_IRQ (1 << 4) + +#define READ_X_LOW (READ_X | READ_LOW) +#define READ_X_HIGH (READ_X | READ_HIGH) +#define READ_Y_LOW (READ_Y | READ_LOW) +#define READ_Y_HIGH (READ_Y | READ_HIGH) /* Our mouse device. */ -typedef struct { - uint16_t port; /* I/O port range start */ - uint16_t portlen; /* length of I/O port range */ - int8_t irq; /* IRQ channel to use */ - uint8_t flags; /* device flags */ - - uint8_t r_magic; /* MAGIC register */ - uint8_t r_ctrl; /* CONTROL register (WR) */ - uint8_t r_intr; /* INTSTAT register (RO) */ - uint8_t r_conf; /* CONFIG register */ - - int8_t x, y; /* current mouse status */ - uint8_t but; +typedef struct mouse_bus_t +{ + int irq; + int timer_index; + int x_delay; + int y_delay; + uint8_t mouse_buttons; + uint8_t mouse_buttons_last; + uint8_t x, y, but; + uint8_t command_val; + uint8_t control_val; + uint8_t config_val; + uint8_t sig_val; + uint16_t toggle_counter; + int interrupts; + int is_inport; } mouse_bus_t; -#define MOUSE_ENABLED 0x80 /* device is enabled for use */ -#define MOUSE_LOGITECH 0x40 /* running in Logitech mode */ -#define MOUSE_MICROSOFT 0x20 /* running in Microsoft mode */ - - -/* Handle a WRITE to a Microsoft-mode register. */ -static void -ms_write(mouse_bus_t *ms, uint16_t port, uint8_t val) -{ -#if 0 - pclog("BUSMOUSE: ms_write(%d,%02x)\n", port, val); -#endif - - switch (port) { - case MSMOUSE_CTRL: /* [00] control register */ - if (val & MSCTRL_RESET) { - /* Reset the interface. */ - ms->r_magic = MAGIC_MSBYTE1; - ms->r_conf = 0x00; - } - - /* Save new register value. */ - ms->r_ctrl = val; - break; - - case MSMOUSE_DATA: /* [01] data register */ - if (ms->r_ctrl == MSCTRL_MODE) { - ms->r_conf = val; - } - break; - - case MSMOUSE_MAGIC: /* [02] magic data register */ - break; - - case MSMOUSE_CONFIG: /* [03] config register */ - ms->r_conf = val; - ms->flags &= ~MOUSE_MICROSOFT; - ms->flags |= MOUSE_LOGITECH; - break; - - default: - break; - } -} - - -/* Handle a WRITE to a LOGITECH-mode register. */ -static void -lt_write(mouse_bus_t *ms, uint16_t port, uint8_t val) -{ - uint8_t b = (ms->r_ctrl ^ val); - -#if 0 - pclog("BUSMOUSE: lt_write(%d,%02x)\n", port, val); -#endif - - switch (port) { - case LTMOUSE_DATA: /* [00] data register */ - break; - - case LTMOUSE_MAGIC: /* [01] magic data register */ - if (val == MAGIC_BYTE1 || val == MAGIC_BYTE2) { - ms->flags |= MOUSE_LOGITECH; - ms->r_magic = val; - } - break; - - case LTMOUSE_CTRL: /* [02] control register */ - if (b & CTRL_FREEZE) { - /* Hold the sampling while we do something. */ - if (! (val & CTRL_FREEZE)) { - /* Reset current state. */ - ms->x = ms->y = 0; - if (ms->but) - /* One more POLL for button-release. */ - ms->but = 0x80; - } - } - - if (b & CTRL_IDIS) { - /* Disable or enable interrupts. */ - /* (we don't do anything for that here..) */ - } - - /* Save new register value. */ - ms->r_ctrl = val; - break; - - case LTMOUSE_CONFIG: /* [03] config register */ - ms->r_conf = val; - break; - - default: - break; - } -} /* Handle a WRITE operation to one of our registers. */ -static void -bm_write(uint16_t port, uint8_t val, void *priv) +static void busmouse_write(uint16_t port, uint8_t val, void *priv) { - mouse_bus_t *ms = (mouse_bus_t *)priv; + mouse_bus_t *busmouse = (mouse_bus_t *)priv; - if (ms->flags & MOUSE_LOGITECH) - lt_write(ms, port - ms->port, val); - - if (ms->flags & MOUSE_MICROSOFT) - ms_write(ms, port - ms->port, val); -} - - -/* Handle a READ from a Microsoft-mode register. */ -static uint8_t -ms_read(mouse_bus_t *ms, uint16_t port) -{ - uint8_t r = 0xff; - - switch (port) { - case MSMOUSE_CTRL: /* [00] control register */ - r = ms->r_ctrl; + switch (port) + { + case BUSM_PORT_CONTROL: + busmouse->control_val = val | 0x0f; + busmouse->interrupts = (val & DISABLE_IRQ) == 0; + picintc(1 << busmouse->irq); break; - - case MSMOUSE_DATA: /* [01] data register */ + + case BUSM_PORT_CONFIG: + busmouse->config_val = val; break; - - case MSMOUSE_MAGIC: /* [02] magic data register */ - /* - * Drivers for the InPort controllers usually start - * by reading this register. If they find 0xDE here, - * they will continue their probe, otherwise no go. - */ - r = ms->r_magic; - - /* For the InPort, switch magic bytes. */ - if (ms->r_magic == MAGIC_MSBYTE1) - ms->r_magic = MAGIC_MSBYTE2; - else - ms->r_magic = MAGIC_MSBYTE1; + + case BUSM_PORT_SIGNATURE: + busmouse->sig_val = val; break; - - case MSMOUSE_CONFIG: /* [03] config register */ - r = ms->r_conf; + + case BUSM_PORT_DATA: break; - - default: - break; - } - -#if 0 - pclog("BUSMOUSE: ms_read(%d): %02x\n", port, r); -#endif - - return(r); -} - - -/* Handle a READ from a LOGITECH-mode register. */ -static uint8_t -lt_read(mouse_bus_t *ms, uint16_t port) -{ - uint8_t r = 0xff; - - switch (port) { - case LTMOUSE_DATA: /* [00] data register */ - if (! (ms->r_ctrl & CTRL_FREEZE)) { - r = 0x00; - } else switch(ms->r_ctrl & CTRL_RD_MASK) { - case CTRL_RD_X_LO: /* X, low bits */ - /* - * Some drivers expect the buttons to - * be in this byte. Others want it in - * the Y-LO byte. --FvK - */ - r = 0x07; - if (ms->but & 0x01) /*LEFT*/ - r &= ~0x04; - if (ms->but & 0x02) /*RIGHT*/ - r &= ~0x01; -#if ENABLE_3BTN - if (ms->but & 0x04) /*MIDDLE*/ - r &= ~0x02; -#endif - r <<= 5; - r |= (ms->x & 0x0f); - break; - - case CTRL_RD_X_HI: /* X, high bits */ - r = (ms->x >> 4) & 0x0f; - break; - - case CTRL_RD_Y_LO: /* Y, low bits */ - r = (ms->y & 0x0f); - break; - - case CTRL_RD_Y_HI: /* Y, high bits */ - /* - * Some drivers expect the buttons to - * be in this byte. Others want it in - * the X-LO byte. --FvK - */ - r = 0x07; - if (ms->but & 0x01) /*LEFT*/ - r &= ~0x04; - if (ms->but & 0x02) /*RIGHT*/ - r &= ~0x01; -#if ENABLE_3BTN - if (ms->but & 0x04) /*MIDDLE*/ - r &= ~0x02; -#endif - r <<= 5; - r |= (ms->y >> 4) & 0x0f; - break; - } - break; - - case LTMOUSE_MAGIC: /* [01] magic data register */ - /* - * Logitech drivers start out by blasting their magic - * value (0xA5) into this register, and then read it - * back to see if that worked. If it did (and we do - * support this) the controller is assumed to be a - * Logitech-protocol one, and not InPort. - */ - r = ms->r_magic; - break; - - case LTMOUSE_CTRL: /* [02] control register */ - /* - * This is the weird stuff mentioned in the file header - * above. Microsoft's "mouse.exe" does some whacky stuff - * to extract the configured IRQ channel from the board. - * - * First, it reads the current value, and then re-reads - * it another 10,000 (yes, really) times. It keeps track - * of whether or not the data has changed, most likely - * to de-bounce reading of a DIP switch for example. This - * first value is assumed to be the 2's complement of the - * actual IRQ value. - * Next, it does this a second time, but now with the - * IDIS bit clear (so, interrupts enabled), which is - * our cue to return the regular (not complemented) value - * to them. - * - * Since we have to fake the initial value and the settling - * of the data a bit later on, we first return a bunch of - * invalid ("random") data, and then the real value. - * - * Yes, this is weird. --FvK - */ - if (ms->r_intr++ < 250) - /* Still settling, return invalid data. */ - r = (ms->r_ctrl&CTRL_IDIS)?0xff:0x00; - else { - /* OK, all good, return correct data. */ - r = (ms->r_ctrl&CTRL_IDIS)?-ms->irq:ms->irq; - ms->r_intr = 0; - } - break; - - case LTMOUSE_CONFIG: /* [03] config register */ - r = ms->r_conf; - break; - - default: - break; - } - -#if 0 - pclog("BUSMOUSE: lt_read(%d): %02x\n", port, r); -#endif - - return(r); + } } /* Handle a READ operation from one of our registers. */ -static uint8_t -bm_read(uint16_t port, void *priv) +static uint8_t busmouse_read(uint16_t port, void *priv) { - mouse_bus_t *ms = (mouse_bus_t *)priv; - uint8_t r = 0xff; - - if (ms->flags & MOUSE_LOGITECH) - r = lt_read(ms, port - ms->port); - - if (ms->flags & MOUSE_MICROSOFT) - r = ms_read(ms, port - ms->port); - + mouse_bus_t *busmouse = (mouse_bus_t *)priv; + uint8_t r = 0; + + switch (port) + { + case BUSM_PORT_CONTROL: + r = busmouse->control_val; + /* This is to allow the driver to see which IRQ the card has "jumpered" + only happens if IRQ's are enabled */ + busmouse->control_val |= 0x0f; + + busmouse->control_val &= ~IRQ_MASK; + busmouse->toggle_counter = (busmouse->toggle_counter + 1) & 0x7ff; + break; + + case BUSM_PORT_DATA: + switch (busmouse->control_val & 0x60) + { + case READ_X_LOW: + r = busmouse->x & 0x0f; + break; + + case READ_X_HIGH: + r = (busmouse->x >> 4) & 0x0f; + break; + + case READ_Y_LOW: + r = busmouse->y & 0x0f; + break; + + case READ_Y_HIGH: + r = ((busmouse->but ^ 7) << 5) | ((busmouse->y >> 4) & 0x0f); + break; + + default: + break; + } + break; + + case BUSM_PORT_CONFIG: + r = busmouse->config_val; + break; + + case BUSM_PORT_SIGNATURE: + r = busmouse->sig_val; + break; + } + return(r); } +static void inport_write(uint16_t port, uint8_t val, void *priv) +{ + mouse_bus_t *inport = (mouse_bus_t *)priv; + + switch (port) + { + case INP_PORT_CONTROL: + switch (val) + { + case INP_CTRL_RESET: + inport->control_val = 0; + inport->command_val = 0; + break; + + case INP_CTRL_COMMAND: + case INP_CTRL_READ_BUTTONS: + case INP_CTRL_READ_X: + case INP_CTRL_READ_Y: + inport->command_val = val; + break; + + case 0x87: + inport->control_val = 0; + inport->command_val = 0x07; + break; + } + break; + + case INP_PORT_DATA: + picintc(1 << inport->irq); + if (val == INP_CTRL_RAISE_IRQ) + { + picint(1 << inport->irq); + } + else + { + switch (inport->command_val) + { + case INP_CTRL_COMMAND: + inport->control_val = val; + inport->interrupts = (val & INP_ENABLE_IRQ) > 0; + break; + + default: + break; + } + } + break; + + case INP_PORT_SIGNATURE: + case INP_PORT_CONFIG: + break; + } +} + +static uint8_t inport_read(uint16_t port, void *priv) +{ + mouse_bus_t *inport = (mouse_bus_t *)priv; + uint8_t r = 0; + + switch (port) + { + case INP_PORT_CONTROL: + r = inport->control_val; + break; + + case INP_PORT_DATA: + switch (inport->command_val) + { + case INP_CTRL_READ_BUTTONS: + r = inport->but; + break; + + case INP_CTRL_READ_X: + r = inport->x; + break; + + case INP_CTRL_READ_Y: + r = inport->y; + break; + + case INP_CTRL_COMMAND: + r = inport->control_val; + break; + } + break; + + case INP_PORT_SIGNATURE: + if (!inport->toggle_counter) + { + r = 0xde; + } + else + { + r = 0x12; + } + inport->toggle_counter ^= 1; + break; + + case INP_PORT_CONFIG: + break; + } + + return(r); +} + +void busmouse_update_mouse_data(void *priv) +{ + mouse_bus_t *busmouse = (mouse_bus_t *)priv; + + int delta_x, delta_y; + int hold; + + if (busmouse->x_delay > 127) { + delta_x = 127; + busmouse->x_delay -= 127; + } else if (busmouse->x_delay < -128) { + delta_x = -128; + busmouse->x_delay += 128; + } else { + delta_x = busmouse->x_delay; + busmouse->x_delay = 0; + } + if (busmouse->y_delay > 127) { + delta_y = 127; + busmouse->y_delay -= 127; + } else if (busmouse->y_delay < -128) { + delta_y = -128; + busmouse->y_delay += 128; + } else { + delta_y = busmouse->y_delay; + busmouse->y_delay = 0; + } + + if (busmouse->is_inport) { + hold = (busmouse->control_val & INP_HOLD_COUNTER) > 0; + } else { + hold = (busmouse->control_val & HOLD_COUNTER) > 0; + } + if (!hold) { + busmouse->x = (uint8_t) delta_x; + busmouse->y = (uint8_t) delta_y; + busmouse->but = busmouse->mouse_buttons; + } +} + +/* Called at 30hz */ +void busmouse_timer_handler(void *priv) +{ + mouse_bus_t *busmouse = (mouse_bus_t *)priv; + + busmouse->timer_index += ((1000000.0 / 30.0) * TIMER_USEC); + + /* The controller updates the data on every interrupt + We just don't copy it to the current_X if the 'hold' bit is set */ + busmouse_update_mouse_data(busmouse); +} /* The emulator calls us with an update on the host mouse device. */ -static uint8_t -bm_poll(int x, int y, int z, int b, void *priv) +static uint8_t busmouse_poll(int x, int y, int z, int b, void *priv) { - mouse_bus_t *ms = (mouse_bus_t *)priv; + mouse_bus_t *busmouse = (mouse_bus_t *)priv; /* Return early if nothing to do. */ - if (!x && !y && !z && (ms->but == b)) return(1); + if (!x && !y && !z && (busmouse->mouse_buttons == b)) return(1); - /* If we are not interested, return. */ - if (!(ms->flags & MOUSE_ENABLED) || - (ms->r_ctrl & CTRL_FREEZE)) return(0); - -#if 0 +#if 1 pclog("BUSMOUSE: poll(%d,%d,%d, %02x)\n", x, y, z, b); #endif + + // scale down the motion + if ((x < -1) || (x > 1)) + x /= 2; + if ((y < -1) || (y > 1)) + y /= 2; + + if (x > 127) x =127; + if (y > 127) y =127; + if (x < -128) x = -128; + if (y < -128) y = -128; + + busmouse->x_delay += x; + busmouse->y_delay += y; + + busmouse->mouse_buttons = (uint8_t)(((b & 1) << 2) | + ((b & 4) >> 1) | ((b & 2) >> 1)); + + if (busmouse->is_inport) + { + if ((busmouse->mouse_buttons & (1<<2)) || + ((busmouse->mouse_buttons_last & (1<<2)) && !(busmouse->mouse_buttons & (1<<2)))) + busmouse->mouse_buttons |= (1<<5); + if ((busmouse->mouse_buttons & (1<<1)) || + ((busmouse->mouse_buttons_last & (1<<1)) && !(busmouse->mouse_buttons & (1<<1)))) + busmouse->mouse_buttons |= (1<<4); + if ((busmouse->mouse_buttons & (1<<0)) || + ((busmouse->mouse_buttons_last & (1<<0)) && !(busmouse->mouse_buttons & (1<<0)))) + busmouse->mouse_buttons |= (1<<3); + busmouse->mouse_buttons_last = busmouse->mouse_buttons; + } - /* Add the delta to our state. */ - x += ms->x; - if (x > 127) - x = 127; - if (x < -128) - x = -128; - ms->x = (int8_t)x; - - y += ms->y; - if (y > 127) - y = 127; - if (y < -128) - y = -128; - ms->y = (int8_t)y; - - ms->but = b; - - /* All set, generate an interrupt. */ - if (! (ms->r_ctrl & CTRL_IDIS)) - picint(1 << ms->irq); - + /* if interrupts are on, fire the interrupt */ + if (busmouse->interrupts) + { + picint(1 << busmouse->irq); + } + return(0); } - /* Release all resources held by the device. */ -static void -bm_close(void *priv) +static void busmouse_close(void *priv) { - mouse_bus_t *ms = (mouse_bus_t *)priv; + mouse_bus_t *busmouse = (mouse_bus_t *)priv; /* Release our I/O range. */ - io_removehandler(ms->port, ms->portlen, - bm_read, NULL, NULL, bm_write, NULL, NULL, ms); + io_removehandler(0x023C, 0x0004, busmouse_read, NULL, NULL, busmouse_write, NULL, NULL, busmouse); - free(ms); + free(busmouse); } - /* Initialize the device for use by the user. */ -static void * -bm_init(void) +static void *busmouse_init(void) { - mouse_bus_t *ms; - - ms = (mouse_bus_t *)malloc(sizeof(mouse_bus_t)); - memset(ms, 0x00, sizeof(mouse_bus_t)); - ms->port = BUSMOUSE_PORT; - ms->portlen = BUSMOUSE_PORTLEN; -#if BUSMOUSE_IRQ - ms->irq = BUSMOUSE_IRQ; -#else - ms->irq = -1; -#endif - - pclog("Logitech/Microsoft Bus Mouse, I/O=%04x, IRQ=%d\n", - ms->port, ms->irq); + mouse_bus_t *busmouse; + + busmouse = (mouse_bus_t *)malloc(sizeof(mouse_bus_t)); + memset(busmouse, 0x00, sizeof(mouse_bus_t)); + + busmouse->is_inport = 0; + busmouse->irq = BUS_MOUSE_IRQ; + /* Initialize registers. */ - ms->r_magic = MAGIC_MSBYTE1; - ms->r_conf = CONFIG_DFLT; - ms->r_ctrl = CTRL_DFLT; - - /* Initialize with Microsoft-mode being default. */ - ms->flags = (MOUSE_ENABLED | MOUSE_MICROSOFT); - + busmouse->control_val = 0x1f; /* The control port value */ + busmouse->config_val = 0x0e; /* The config port value */ + + /* Common. */ + busmouse->command_val = 0; + busmouse->toggle_counter = 0; + busmouse->interrupts = 0; + /* Request an I/O range. */ - io_sethandler(ms->port, ms->portlen, - bm_read, NULL, NULL, bm_write, NULL, NULL, ms); - + io_sethandler(0x023C, 0x0004, busmouse_read, NULL, NULL, busmouse_write, NULL, NULL, busmouse); + timer_add(busmouse_timer_handler, &busmouse->timer_index, TIMER_ALWAYS_ENABLED, busmouse); + /* Return our private data to the I/O layer. */ - return(ms); + return(busmouse); +} + +/* Initialize the device for use by the user. */ +static void *inport_init(void) +{ + mouse_bus_t *inport; + + inport = (mouse_bus_t *)malloc(sizeof(mouse_bus_t)); + memset(inport, 0x00, sizeof(mouse_bus_t)); + + inport->is_inport = 1; + inport->irq = BUS_MOUSE_IRQ; + + /* Initialize registers. */ + inport->control_val = 0x00; /* The control port value */ + inport->config_val = 0x00; /* The config port value */ + + /* Common. */ + inport->command_val = 0; + inport->toggle_counter = 0; + inport->interrupts = 0; + + /* Request an I/O range. */ + io_sethandler(0x023C, 0x0004, inport_read, NULL, NULL, inport_write, NULL, NULL, inport); + timer_add(busmouse_timer_handler, &inport->timer_index, TIMER_ALWAYS_ENABLED, inport); + + /* Return our private data to the I/O layer. */ + return(inport); } - -mouse_t mouse_bus = { +mouse_t mouse_bus = +{ "Bus Mouse", "msbus", MOUSE_TYPE_BUS, - bm_init, - bm_close, - bm_poll + busmouse_init, + busmouse_close, + busmouse_poll +}; + +mouse_t mouse_inport = +{ + "InPort Mouse", + "inport", + MOUSE_TYPE_INPORT, + inport_init, + busmouse_close, + busmouse_poll }; diff --git a/src/mouse_bus.h b/src/mouse_bus.h index 24eeb50ff..3f931ca86 100644 --- a/src/mouse_bus.h +++ b/src/mouse_bus.h @@ -23,12 +23,8 @@ # define MOUSE_BUS_H -#define BUSMOUSE_PORT 0x023c -#define BUSMOUSE_PORTLEN 4 -#define BUSMOUSE_IRQ 5 - - extern mouse_t mouse_bus; +extern mouse_t mouse_inport; #endif /*MOUSE_BUS_H*/ From 9919de86ff208dffc56b3982c2c7cf0bcb07d96a Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Jul 2017 18:42:29 +0200 Subject: [PATCH 26/82] Applied the mainline PCem AGI stall commit; Fixed the mouse list order mess. --- src/CPU/codegen.h | 41 +- src/CPU/codegen_ops.h | 7 + src/CPU/codegen_timing_486.c | 57 ++- src/CPU/codegen_timing_686.c | 623 ++++++++++++------------ src/CPU/codegen_timing_pentium.c | 805 +++++++++++++++---------------- src/CPU/codegen_timing_winchip.c | 55 ++- src/Makefile.mingw | 3 +- src/mouse.c | 21 +- src/mouse.h | 18 +- src/mouse_bus.c | 5 +- 10 files changed, 852 insertions(+), 783 deletions(-) diff --git a/src/CPU/codegen.h b/src/CPU/codegen.h index d9175d3a5..982a95872 100644 --- a/src/CPU/codegen.h +++ b/src/CPU/codegen.h @@ -1,4 +1,8 @@ +#ifndef _CODEGEN_H_ +#define _CODEGEN_H_ + #include "../mem.h" +#include "x86_ops.h" #ifdef __amd64__ #include "codegen_x86-64.h" @@ -35,10 +39,10 @@ typedef struct codeblock_t { - uint64_t page_mask, page_mask2; + uint64_t page_mask, page_mask2; uint64_t *dirty_mask, *dirty_mask2; - uint64_t cmp; - + uint64_t cmp; + /*Previous and next pointers, for the codeblock list associated with each physical page. Two sets of pointers, as a codeblock can be present in two pages.*/ @@ -59,7 +63,7 @@ typedef struct codeblock_t uint32_t _cs; uint32_t endpc; uint32_t phys, phys_2; - uint32_t status; + uint32_t status; uint32_t flags; uint8_t data[2048]; @@ -70,7 +74,7 @@ typedef struct codeblock_t /*Code block is always entered with the same FPU top-of-stack*/ #define CODEBLOCK_STATIC_TOP 2 -static __inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) +static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) { codeblock_t *block = pages[phys >> 12].head; uint64_t a = _cs | ((uint64_t)phys << 32); @@ -88,7 +92,7 @@ static __inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) return block; } -static __inline void codeblock_tree_add(codeblock_t *new_block) +static inline void codeblock_tree_add(codeblock_t *new_block) { codeblock_t *block = pages[new_block->phys >> 12].head; uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); @@ -122,7 +126,7 @@ static __inline void codeblock_tree_add(codeblock_t *new_block) } } -static __inline void codeblock_tree_delete(codeblock_t *block) +static inline void codeblock_tree_delete(codeblock_t *block) { codeblock_t *parent = block->parent; @@ -252,6 +256,7 @@ void codegen_block_init(uint32_t phys_addr); void codegen_block_remove(); void codegen_block_start_recompile(codeblock_t *block); void codegen_block_end_recompile(codeblock_t *block); +void codegen_block_end(); void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc); void codegen_generate_seg_restore(); void codegen_set_op32(); @@ -300,7 +305,7 @@ extern int block_pos; #define CPU_BLOCK_END() cpu_block_end = 1 -static __inline void addbyte(uint8_t val) +static inline void addbyte(uint8_t val) { codeblock[block_current].data[block_pos++] = val; if (block_pos >= BLOCK_MAX) @@ -309,10 +314,10 @@ static __inline void addbyte(uint8_t val) } } -static __inline void addword(uint16_t val) +static inline void addword(uint16_t val) { - uint16_t *p = (uint16_t *)&codeblock[block_current].data[block_pos]; - *p = val; + uint16_t *p = (uint16_t *) &codeblock[block_current].data[block_pos]; + *p = val; block_pos += 2; if (block_pos >= BLOCK_MAX) { @@ -320,10 +325,10 @@ static __inline void addword(uint16_t val) } } -static __inline void addlong(uint32_t val) +static inline void addlong(uint32_t val) { - uint32_t *p = (uint32_t *)&codeblock[block_current].data[block_pos]; - *p = val; + uint32_t *p = (uint32_t *) &codeblock[block_current].data[block_pos]; + *p = val; block_pos += 4; if (block_pos >= BLOCK_MAX) { @@ -331,10 +336,10 @@ static __inline void addlong(uint32_t val) } } -static __inline void addquad(uint64_t val) +static inline void addquad(uint64_t val) { - uint64_t *p = (uint64_t *)&codeblock[block_current].data[block_pos]; - *p = val; + uint64_t *p = (uint64_t *) &codeblock[block_current].data[block_pos]; + *p = val; block_pos += 8; if (block_pos >= BLOCK_MAX) { @@ -360,3 +365,5 @@ extern int codegen_fpu_loaded_iq[8]; extern int codegen_reg_loaded[8]; extern int codegen_in_recompile; + +#endif diff --git a/src/CPU/codegen_ops.h b/src/CPU/codegen_ops.h index bda54029a..53f5b34d2 100644 --- a/src/CPU/codegen_ops.h +++ b/src/CPU/codegen_ops.h @@ -1,3 +1,8 @@ +#ifndef _CODEGEN_OPS_H_ +#define _CODEGEN_OPS_H_ + +#include "codegen.h" + typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block); extern RecompOpFn recomp_opcodes[512]; @@ -37,3 +42,5 @@ RecompOpFn recomp_opcodes_REPNE[512]; #define REG_DH 6 #define REG_BL 3 #define REG_BH 7 + +#endif diff --git a/src/CPU/codegen_timing_486.c b/src/CPU/codegen_timing_486.c index ddcbc260c..8317e2c49 100644 --- a/src/CPU/codegen_timing_486.c +++ b/src/CPU/codegen_timing_486.c @@ -1,10 +1,12 @@ #include "../ibm.h" -#include "../mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" +#include "../mem.h" #include "codegen.h" +#include "codegen_ops.h" +#include "codegen_timing_common.h" #define CYCLES(c) (int *)c #define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8)) @@ -247,14 +249,27 @@ static int *opcode_timings_8x[8] = { &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm }; +static int *opcode_timings_8x_mod3[8] = +{ + &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm +}; +static int *opcode_timings_81[8] = +{ + &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm +}; +static int *opcode_timings_81_mod3[8] = +{ + &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm +}; static int timing_count; static uint8_t last_prefix; +static uint32_t regmask_modified; -static __inline int COUNT(int *c, int op_32) +static inline int COUNT(int *c, int op_32) { if ((uintptr_t)c <= 10000) - return (int)c; + return (int)(uintptr_t)c; if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff)) { if (op_32 & 0x100) @@ -266,6 +281,7 @@ static __inline int COUNT(int *c, int op_32) void codegen_timing_486_block_start() { + regmask_modified = 0; } void codegen_timing_486_start() @@ -283,82 +299,107 @@ void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat) void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { int **timings; + uint64_t *deps; int mod3 = ((fetchdat & 0xc0) == 0xc0); - + int bit8 = !(opcode & 1); + switch (last_prefix) { case 0x0f: timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; default: switch (opcode) { - case 0x80: case 0x81: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_mod3 : opcode_timings_8x; - if (!mod3) - opcode = (fetchdat >> 3) & 7; + case 0x80: case 0x82: case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; break; case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xf6: timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } } timing_count += COUNT(timings[opcode], op_32); + if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32)) + timing_count++; /*AGI stall*/ codegen_block_cycles += timing_count; + + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } void codegen_timing_486_block_end() diff --git a/src/CPU/codegen_timing_686.c b/src/CPU/codegen_timing_686.c index 550c7e231..f62e63429 100644 --- a/src/CPU/codegen_timing_686.c +++ b/src/CPU/codegen_timing_686.c @@ -2,6 +2,7 @@ - X/Y pairing - FPU/FXCH pairing - Prefix decode delay + - AGI stalls Elements not taken into account : - Branch prediction (beyond most simplistic approximation) - FPU queue @@ -15,6 +16,7 @@ #include "x87.h" #include "../mem.h" #include "codegen.h" +#include "codegen_timing_common.h" /*Instruction has different execution time for 16 and 32 bit data. Does not pair */ #define CYCLES_HAS_MULTI (1 << 31) @@ -33,11 +35,6 @@ #define CYCLES_MASK ((1 << 7) - 1) -/*Instruction is MMX shift or pack/unpack instruction*/ -#define MMX_SHIFTPACK (1 << 7) -/*Instruction is MMX multiply instruction*/ -#define MMX_MULTIPLY (1 << 8) - /*Instruction does not pair*/ #define PAIR_NP (0 << 29) /*Instruction pairs in X pipe only*/ @@ -49,35 +46,6 @@ #define PAIR_MASK (3 << 29) -/*Instruction has input dependency on register in REG field*/ -#define SRCDEP_REG (1 << 9) -/*Instruction has input dependency on register in R/M field*/ -#define SRCDEP_RM (1 << 10) -/*Instruction modifies register in REG field*/ -#define DSTDEP_REG (1 << 11) -/*Instruction modifies register in R/M field*/ -#define DSTDEP_RM (1 << 12) - -/*Instruction has input dependency on given register*/ -#define SRCDEP_EAX (1 << 13) -#define SRCDEP_ECX (1 << 14) -#define SRCDEP_EDX (1 << 15) -#define SRCDEP_EBX (1 << 16) -#define SRCDEP_ESP (1 << 17) -#define SRCDEP_EBP (1 << 18) -#define SRCDEP_ESI (1 << 19) -#define SRCDEP_EDI (1 << 20) - -/*Instruction modifies given register*/ -#define DSTDEP_EAX (1 << 21) -#define DSTDEP_ECX (1 << 22) -#define DSTDEP_EDX (1 << 23) -#define DSTDEP_EBX (1 << 24) -#define DSTDEP_ESP (1 << 25) -#define DSTDEP_EBP (1 << 26) -#define DSTDEP_ESI (1 << 27) -#define DSTDEP_EDI (1 << 28) - #define INVALID 0 static int prev_full; @@ -85,119 +53,74 @@ static uint32_t prev_opcode; static uint32_t *prev_timings; static uint32_t prev_op_32; static uint32_t prev_regmask; +static uint64_t *prev_deps; +static uint32_t prev_fetchdat; -#define REGMASK_MMX (1 << 8) +static uint32_t regmask_modified; -static uint32_t get_srcdep_mask(uint32_t data, uint32_t fetchdat, int bit8) -{ - uint32_t mask = 0; - if (data & SRCDEP_REG) - { - int reg = (fetchdat >> 3) & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - if (data & SRCDEP_RM) - { - int reg = fetchdat & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - mask |= ((data >> 16) & 0xff); - if (data & (MMX_SHIFTPACK | MMX_MULTIPLY)) - mask |= REGMASK_MMX; - - return mask; -} - -static uint32_t get_dstdep_mask(uint32_t data, uint32_t fetchdat, int bit8) -{ - uint32_t mask = 0; - if (data & DSTDEP_REG) - { - int reg = (fetchdat >> 3) & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - if (data & DSTDEP_RM) - { - int reg = fetchdat & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - mask |= ((data >> 24) & 0xff); - if (data & (MMX_SHIFTPACK | MMX_MULTIPLY)) - mask |= REGMASK_MMX; - - return mask; -} static uint32_t opcode_timings[256] = { -/* ADD ADD ADD ADD*/ -/*00*/ PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* ADD ADD PUSH ES POP ES*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(3), -/* OR OR OR OR*/ - PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* OR OR PUSH CS */ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, INVALID, +/* ADD ADD ADD ADD*/ +/*00*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* ADD ADD PUSH ES POP ES*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* OR OR OR OR*/ + PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* OR OR PUSH CS */ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), INVALID, -/* ADC ADC ADC ADC*/ -/*10*/ PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* ADC ADC PUSH SS POP SS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ - PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* SBB SBB PUSH DS POP DS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(3), +/* ADC ADC ADC ADC*/ +/*10*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* ADC ADC PUSH SS POP SS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* SBB SBB SBB SBB*/ + PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* SBB SBB PUSH DS POP DS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* AND AND AND AND*/ -/*20*/ PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* AND AND DAA*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(7), -/* SUB SUB SUB SUB*/ - PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* SUB SUB DAS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(7), +/* AND AND AND AND*/ +/*20*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* AND AND DAA*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), +/* SUB SUB SUB SUB*/ + PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* SUB SUB DAS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), -/* XOR XOR XOR XOR*/ -/*30*/ PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* XOR XOR AAA*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(7), -/* CMP CMP CMP CMP*/ - PAIR_XY | CYCLES_RM | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG, -/* CMP CMP AAS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX, INVALID, PAIR_NP | CYCLES(7), +/* XOR XOR XOR XOR*/ +/*30*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* XOR XOR AAA*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), +/* CMP CMP CMP CMP*/ + PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, +/* CMP CMP AAS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), -/* INC EAX INC ECX INC EDX INC EBX*/ -/*40*/ PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* INC ESP INC EBP INC ESI INC EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, -/* DEC EAX DEC ECX DEC EDX DEC EBX*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* DEC ESP DEC EBP DEC ESI DEC EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* INC ESP INC EBP INC ESI INC EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, -/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ -/*50*/ PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX | SRCDEP_ESP | DSTDEP_ESP, -/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI | SRCDEP_ESP | DSTDEP_ESP, -/* POP EAX POP ECX POP EDX POP EBX*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX | SRCDEP_ESP | DSTDEP_ESP, -/* POP ESP POP EBP POP ESI POP EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI | SRCDEP_ESP | DSTDEP_ESP, +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* POP EAX POP ECX POP EDX POP EBX*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* POP ESP POP EBP POP ESI POP EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, -/* PUSHA POPA BOUND ARPL*/ -/*60*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(9), - INVALID, INVALID, INVALID, INVALID, -/* PUSH imm IMUL PUSH imm IMUL*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(10), PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(10), -/* INSB INSW OUTSB OUTSW*/ - PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), +/* PUSHA POPA BOUND ARPL*/ +/*60*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(9), + INVALID, INVALID, INVALID, INVALID, +/* PUSH imm IMUL PUSH imm IMUL*/ + PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(10), PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(10), +/* INSB INSW OUTSB OUTSW*/ + PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), /* Jxx*/ /*70*/ PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, @@ -205,37 +128,37 @@ static uint32_t opcode_timings[256] = PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, -/*80*/ INVALID, INVALID, INVALID, INVALID, -/* TEST TEST XCHG XCHG*/ - PAIR_XY | CYCLES_RM | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), -/* MOV MOV MOV MOV*/ - PAIR_XY | CYCLES_REG | SRCDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG, PAIR_XY | CYCLES_REG | DSTDEP_REG, PAIR_XY | CYCLES_REG | DSTDEP_REG, -/* MOV from seg LEA MOV to seg POP*/ - PAIR_XY | CYCLES(1), PAIR_XY | CYCLES_REG | DSTDEP_REG, CYCLES(3), PAIR_XY | CYCLES(1), +/*80*/ INVALID, INVALID, INVALID, INVALID, +/* TEST TEST XCHG XCHG*/ + PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), +/* MOV MOV MOV MOV*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* MOV from seg LEA MOV to seg POP*/ + PAIR_XY | CYCLES(1), PAIR_XY | CYCLES_REG, CYCLES(3), PAIR_XY | CYCLES(1), -/* NOP XCHG XCHG XCHG*/ -/*90*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), -/* XCHG XCHG XCHG XCHG*/ - PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), -/* CBW CWD CALL far WAIT*/ - PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(2), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), -/* PUSHF POPF SAHF LAHF*/ - PAIR_XY | CYCLES(2) | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES(9) | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(2), +/* NOP XCHG XCHG XCHG*/ +/*90*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), +/* XCHG XCHG XCHG XCHG*/ + PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), +/* CBW CWD CALL far WAIT*/ + PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(2), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), +/* PUSHF POPF SAHF LAHF*/ + PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(2), -/* MOV MOV MOV MOV*/ -/*a0*/ PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX, -/* MOVSB MOVSW CMPSB CMPSW*/ - PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), -/* TEST TEST STOSB STOSW*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), -/* LODSB LODSW SCASB SCASW*/ - PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), +/* MOV MOV MOV MOV*/ +/*a0*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* MOVSB MOVSW CMPSB CMPSW*/ + PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), +/* TEST TEST STOSB STOSW*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), +/* LODSB LODSW SCASB SCASW*/ + PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), /* MOV*/ -/*b0*/ PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_ECX, PAIR_XY | CYCLES_REG | DSTDEP_EDX, PAIR_XY | CYCLES_REG | DSTDEP_EBX, - PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_ECX, PAIR_XY | CYCLES_REG | DSTDEP_EDX, PAIR_XY | CYCLES_REG | DSTDEP_EBX, - PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_ECX, PAIR_XY | CYCLES_REG | DSTDEP_EDX, PAIR_XY | CYCLES_REG | DSTDEP_EBX, - PAIR_XY | CYCLES_REG | DSTDEP_ESP, PAIR_XY | CYCLES_REG | DSTDEP_EBP, PAIR_XY | CYCLES_REG | DSTDEP_ESI, PAIR_XY | CYCLES_REG | DSTDEP_EDI, +/*b0*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* RET imm RET*/ /*c0*/ INVALID, INVALID, PAIR_X_BRANCH | CYCLES(3), PAIR_X_BRANCH | CYCLES(2), @@ -253,7 +176,7 @@ static uint32_t opcode_timings[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /* LOOPNE LOOPE LOOP JCXZ*/ -/*e0*/ PAIR_X_BRANCH| CYCLES_BRANCH | SRCDEP_ECX, PAIR_X_BRANCH | CYCLES_BRANCH | SRCDEP_ECX, PAIR_X_BRANCH | CYCLES_BRANCH | SRCDEP_ECX, PAIR_X_BRANCH | CYCLES_BRANCH | SRCDEP_ECX, +/*e0*/ PAIR_X_BRANCH| CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, /* IN AL IN AX OUT_AL OUT_AX*/ PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), /* CALL JMP JMP JMP*/ @@ -273,68 +196,67 @@ static uint32_t opcode_timings[256] = static uint32_t opcode_timings_mod3[256] = { -/* ADD ADD ADD ADD*/ -/*00*/ PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* ADD ADD PUSH ES POP ES*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(3), -/* OR OR OR OR*/ - PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* OR OR PUSH CS */ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, INVALID, +/* ADD ADD ADD ADD*/ +/*00*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* ADD ADD PUSH ES POP ES*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* OR OR OR OR*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* OR OR PUSH CS */ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), INVALID, -/* ADC ADC ADC ADC*/ -/*10*/ PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* ADC ADC PUSH SS POP SS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ - PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* SBB SBB PUSH DS POP DS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, PAIR_NP | CYCLES(3), +/* ADC ADC ADC ADC*/ +/*10*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* ADC ADC PUSH SS POP SS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* SBB SBB SBB SBB*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* SBB SBB PUSH DS POP DS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* AND AND AND AND*/ -/*20*/ PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* AND AND DAA*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(9), -/* SUB SUB SUB SUB*/ - PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* SUB SUB DAS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(9), +/* AND AND AND AND*/ +/*20*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* AND AND DAA*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), +/* SUB SUB SUB SUB*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* SUB SUB DAS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), -/* XOR XOR XOR XOR*/ -/*30*/ PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* XOR XOR AAA*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(7), -/* CMP CMP CMP CMP*/ - PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_RM | SRCDEP_REG, -/* CMP CMP AAS*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | SRCDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_EAX, INVALID, PAIR_NP | CYCLES(7), +/* XOR XOR XOR XOR*/ +/*30*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* XOR XOR AAA*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), +/* CMP CMP CMP CMP*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* CMP CMP AAS*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), -/* INC EAX INC ECX INC EDX INC EBX*/ -/*40*/ PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* INC ESP INC EBP INC ESI INC EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, -/* DEC EAX DEC ECX DEC EDX DEC EBX*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* DEC ESP DEC EBP DEC ESI DEC EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* INC ESP INC EBP INC ESI INC EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, -/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ -/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ -/*50*/ PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX | SRCDEP_ESP | DSTDEP_ESP, -/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI | SRCDEP_ESP | DSTDEP_ESP, -/* POP EAX POP ECX POP EDX POP EBX*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX | SRCDEP_ESP | DSTDEP_ESP, -/* POP ESP POP EBP POP ESI POP EDI*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI | SRCDEP_ESP | DSTDEP_ESP, +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* POP EAX POP ECX POP EDX POP EBX*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* POP ESP POP EBP POP ESI POP EDI*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, -/* PUSHA POPA BOUND ARPL*/ -/*60*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(9), - INVALID, INVALID, INVALID, INVALID, -/* PUSH imm IMUL PUSH imm IMUL*/ - PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES(10), PAIR_XY | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES(10), -/* INSB INSW OUTSB OUTSW*/ - PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), +/* PUSHA POPA BOUND ARPL*/ +/*60*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(9), + INVALID, INVALID, INVALID, INVALID, +/* PUSH imm IMUL PUSH imm IMUL*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(10), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(10), +/* INSB INSW OUTSB OUTSW*/ + PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), /* Jxx*/ /*70*/ PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, @@ -342,13 +264,13 @@ static uint32_t opcode_timings_mod3[256] = PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, -/*80*/ PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, -/* TEST TEST XCHG XCHG*/ - PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), -/* MOV MOV MOV MOV*/ - PAIR_XY | CYCLES_REG | SRCDEP_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_REG, PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_REG, -/* MOV from seg LEA MOV to seg POP*/ - PAIR_XY | CYCLES(1), PAIR_XY | CYCLES_REG | DSTDEP_REG, PAIR_NP | CYCLES(3), PAIR_XY | CYCLES(1), +/*80*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* TEST TEST XCHG XCHG*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), +/* MOV MOV MOV MOV*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* MOV from seg LEA MOV to seg POP*/ + PAIR_XY | CYCLES(1), PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(3), PAIR_XY | CYCLES(1), /* NOP XCHG XCHG XCHG*/ /*90*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), @@ -357,22 +279,22 @@ static uint32_t opcode_timings_mod3[256] = /* CBW CWD CALL far WAIT*/ PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(2), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), /* PUSHF POPF SAHF LAHF*/ - PAIR_XY | CYCLES(2) | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES(9) | SRCDEP_ESP | DSTDEP_ESP, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(2), + PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(2), /* MOV MOV MOV MOV*/ -/*a0*/ PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX, +/*a0*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* MOVSB MOVSW CMPSB CMPSW*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), /* TEST TEST STOSB STOSW*/ - PAIR_XY | CYCLES_REG | SRCDEP_EAX, PAIR_XY | CYCLES_REG | SRCDEP_EAX, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), /* LODSB LODSW SCASB SCASW*/ PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), /* MOV*/ -/*b0*/ PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_ECX, PAIR_XY | CYCLES_REG | DSTDEP_EDX, PAIR_XY | CYCLES_REG | DSTDEP_EBX, - PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_ECX, PAIR_XY | CYCLES_REG | DSTDEP_EDX, PAIR_XY | CYCLES_REG | DSTDEP_EBX, - PAIR_XY | CYCLES_REG | DSTDEP_EAX, PAIR_XY | CYCLES_REG | DSTDEP_ECX, PAIR_XY | CYCLES_REG | DSTDEP_EDX, PAIR_XY | CYCLES_REG | DSTDEP_EBX, - PAIR_XY | CYCLES_REG | DSTDEP_ESP, PAIR_XY | CYCLES_REG | DSTDEP_EBP, PAIR_XY | CYCLES_REG | DSTDEP_ESI, PAIR_XY | CYCLES_REG | DSTDEP_EDI, +/*b0*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* RET imm RET*/ /*c0*/ INVALID, INVALID, PAIR_X_BRANCH | CYCLES(3), PAIR_X_BRANCH | CYCLES(2), @@ -391,7 +313,7 @@ static uint32_t opcode_timings_mod3[256] = INVALID, INVALID, INVALID, INVALID, /* LOOPNE LOOPE LOOP JCXZ*/ -/*e0*/ PAIR_X_BRANCH| CYCLES_BRANCH | SRCDEP_ECX, PAIR_X_BRANCH | CYCLES_BRANCH | SRCDEP_ECX, PAIR_X_BRANCH | CYCLES_BRANCH | SRCDEP_ECX, PAIR_X_BRANCH | CYCLES_BRANCH | SRCDEP_ECX, +/*e0*/ PAIR_X_BRANCH| CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, /* IN AL IN AX OUT_AL OUT_AX*/ PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), /* CALL JMP JMP JMP*/ @@ -441,15 +363,15 @@ static uint32_t opcode_timings_0f[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, -/*60*/ PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, - PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, - INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, +/*60*/ PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, + INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, -/*70*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES(1), - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, +/*70*/ INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES(1), + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, /*80*/ PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, @@ -476,20 +398,20 @@ static uint32_t opcode_timings_0f[256] = PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(4), -/*d0*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, - INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, +/*d0*/ INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, + INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, -/*e0*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, INVALID, - INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, +/*e0*/ INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, + INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, -/*f0*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, PAIR_X | MMX_SHIFTPACK | CYCLES_RM, - INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, - PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, +/*f0*/ INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, + INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, + PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, }; static uint32_t opcode_timings_0f_mod3[256] = { @@ -523,15 +445,15 @@ static uint32_t opcode_timings_0f_mod3[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, -/*60*/ PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, - PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, - INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, +/*60*/ PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, + INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, -/*70*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES(1), - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, +/*70*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES(1), + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, /*80*/ PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, @@ -557,20 +479,20 @@ static uint32_t opcode_timings_0f_mod3[256] = PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), -/*d0*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, - INVALID, PAIR_X | MMX_MULTIPLY | CYCLES_REG, INVALID, INVALID, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, +/*d0*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, + INVALID, PAIR_X | CYCLES_REG, INVALID, INVALID, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, -/*e0*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, INVALID, - INVALID, PAIR_X | MMX_MULTIPLY | CYCLES_REG, INVALID, INVALID, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, +/*e0*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, + INVALID, PAIR_X | CYCLES_REG, INVALID, INVALID, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, -/*f0*/ INVALID, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, PAIR_X | MMX_SHIFTPACK | CYCLES_REG, - INVALID, PAIR_X | MMX_MULTIPLY | CYCLES_REG, INVALID, INVALID, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, +/*f0*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, + INVALID, PAIR_X | CYCLES_REG, INVALID, INVALID, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, }; static uint32_t opcode_timings_shift[8] = @@ -580,8 +502,8 @@ static uint32_t opcode_timings_shift[8] = }; static uint32_t opcode_timings_shift_mod3[8] = { - PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES(3) | DSTDEP_RM, PAIR_XY | CYCLES(4) | DSTDEP_RM, - PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, }; static uint32_t opcode_timings_shift_imm[8] = { @@ -590,18 +512,18 @@ static uint32_t opcode_timings_shift_imm[8] = }; static uint32_t opcode_timings_shift_imm_mod3[8] = { - PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES(3) | DSTDEP_RM, PAIR_XY | CYCLES(4) | DSTDEP_RM, - PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, PAIR_XY | CYCLES_REG | DSTDEP_RM, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, }; static uint32_t opcode_timings_shift_cl[8] = { - PAIR_XY | CYCLES(2) | SRCDEP_ECX, PAIR_XY | CYCLES(2) | SRCDEP_ECX, PAIR_XY | CYCLES(8) | SRCDEP_ECX, PAIR_XY | CYCLES(9) | SRCDEP_ECX, - PAIR_XY | CYCLES(2) | SRCDEP_ECX, PAIR_XY | CYCLES(2) | SRCDEP_ECX, PAIR_XY | CYCLES(2) | SRCDEP_ECX, PAIR_XY | CYCLES(2) | SRCDEP_ECX, + PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), + PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), }; static uint32_t opcode_timings_shift_cl_mod3[8] = { - PAIR_XY | CYCLES(2) | DSTDEP_RM | SRCDEP_ECX, PAIR_XY | CYCLES(2) | DSTDEP_RM | SRCDEP_ECX, PAIR_XY | CYCLES(8) | DSTDEP_RM | SRCDEP_ECX, PAIR_XY | CYCLES(9) | DSTDEP_RM | SRCDEP_ECX, - PAIR_XY | CYCLES(2) | DSTDEP_RM | SRCDEP_ECX, PAIR_XY | CYCLES(2) | DSTDEP_RM | SRCDEP_ECX, PAIR_XY | CYCLES(2) | DSTDEP_RM | SRCDEP_ECX, PAIR_XY | CYCLES(2) | DSTDEP_RM | SRCDEP_ECX, + PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), + PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), }; static uint32_t opcode_timings_f6[8] = @@ -613,22 +535,22 @@ static uint32_t opcode_timings_f6[8] = }; static uint32_t opcode_timings_f6_mod3[8] = { -/* TST NOT NEG*/ - PAIR_XY | CYCLES_REG | SRCDEP_RM, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), +/* TST NOT NEG*/ + PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(18) }; static uint32_t opcode_timings_f7[8] = { /* TST NOT NEG*/ - PAIR_XY | CYCLES_REG | SRCDEP_RM, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), + PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) }; static uint32_t opcode_timings_f7_mod3[8] = { /* TST NOT NEG*/ - PAIR_XY | CYCLES_REG | SRCDEP_RM, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), + PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) }; @@ -637,14 +559,14 @@ static uint32_t opcode_timings_ff[8] = /* INC DEC CALL CALL far*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), /* JMP JMP far PUSH*/ - PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), PAIR_XY | CYCLES(1) | SRCDEP_ESP | DSTDEP_ESP, INVALID + PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), PAIR_XY | CYCLES(1), INVALID }; static uint32_t opcode_timings_ff_mod3[8] = { -/* INC DEC CALL CALL far*/ - PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_XY | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), -/* JMP JMP far PUSH*/ - PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), PAIR_XY | CYCLES(2) | SRCDEP_ESP | DSTDEP_ESP, INVALID +/* INC DEC CALL CALL far*/ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), +/* JMP JMP far PUSH*/ + PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), PAIR_XY | CYCLES(2), INVALID }; static uint32_t opcode_timings_d8[8] = @@ -812,8 +734,23 @@ static uint32_t opcode_timings_df_mod3[8] = static uint32_t opcode_timings_8x[8] = { - PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, - PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RMW | SRCDEP_REG, PAIR_XY | CYCLES_RM | SRCDEP_REG + PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, + PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM +}; +static uint32_t opcode_timings_8x_mod3[8] = +{ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG +}; +static uint32_t opcode_timings_81[8] = +{ + PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, + PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM +}; +static uint32_t opcode_timings_81_mod3[8] = +{ + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG }; static int decode_delay; @@ -836,6 +773,7 @@ static inline int COUNT(uint32_t c, int op_32) void codegen_timing_686_block_start() { prev_full = decode_delay = 0; + regmask_modified = 0; } void codegen_timing_686_start() @@ -853,9 +791,20 @@ void codegen_timing_686_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; } +static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) +{ + uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); + + if (addr_regmask & IMPL_ESP) + addr_regmask |= (1 << REG_ESP); + + return regmask_modified & addr_regmask; +} + void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { uint32_t *timings; + uint64_t *deps; int mod3 = ((fetchdat & 0xc0) == 0xc0); int bit8 = !(opcode & 1); @@ -863,80 +812,101 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { case 0x0f: timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; default: switch (opcode) { - case 0x80: case 0x81: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_mod3 : opcode_timings_8x; - if (!mod3) - opcode = (fetchdat >> 3) & 7; + case 0x80: case 0x82: case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; break; case 0xc0: case 0xc1: timings = mod3 ? opcode_timings_shift_imm_mod3 : opcode_timings_shift_imm; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; - + case 0xd0: case 0xd1: timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; - + case 0xd2: case 0xd3: timings = mod3 ? opcode_timings_shift_cl_mod3 : opcode_timings_shift_cl; + deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; opcode = (fetchdat >> 3) & 7; break; case 0xf6: timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } } @@ -946,33 +916,43 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if (prev_full) { - uint8_t regmask = get_srcdep_mask(timings[opcode], fetchdat, bit8); - + uint32_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, op_32); + int agi_stall = 0; + + if (regmask & IMPL_ESP) + regmask |= SRCDEP_ESP | DSTDEP_ESP; + + if (check_agi(prev_deps, prev_opcode, prev_fetchdat, prev_op_32)) + agi_stall = 2; + /*Second instruction in the pair*/ if ((timings[opcode] & PAIR_MASK) == PAIR_NP) { /*Instruction can not pair with previous*/ /*Run previous now*/ - codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay; - decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1; + codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + regmask_modified = prev_regmask; } else if (((timings[opcode] & PAIR_MASK) == PAIR_X || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) && (prev_timings[opcode] & PAIR_MASK) == PAIR_X) { /*Instruction can not pair with previous*/ /*Run previous now*/ - codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay; - decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1; + codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + regmask_modified = prev_regmask; } else if (prev_regmask & regmask) { /*Instruction can not pair with previous*/ /*Run previous now*/ - codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay; - decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1; + codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + regmask_modified = prev_regmask; } else { @@ -982,9 +962,14 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if (!t_pair) fatal("Pairable 0 cycles! %02x %02x\n", opcode, prev_opcode); - codegen_block_cycles += t_pair; - decode_delay = (-t_pair) + 1; + + if (check_agi(deps, opcode, fetchdat, op_32)) + agi_stall = 2; + + codegen_block_cycles += t_pair + agi_stall; + decode_delay = (-t_pair) + 1 + agi_stall; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | prev_regmask; prev_full = 0; return; } @@ -996,8 +981,14 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if ((timings[opcode] & PAIR_MASK) == PAIR_NP || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) { /*Instruction not pairable*/ - codegen_block_cycles += COUNT(timings[opcode], op_32) + decode_delay; - decode_delay = (-COUNT(timings[opcode], op_32)) + 1; + int agi_stall = 0; + + if (check_agi(deps, opcode, fetchdat, op_32)) + agi_stall = 2; + + codegen_block_cycles += COUNT(timings[opcode], op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(timings[opcode], op_32)) + 1 + agi_stall; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } else { @@ -1006,7 +997,11 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) prev_opcode = opcode; prev_timings = timings; prev_op_32 = op_32; - prev_regmask = get_dstdep_mask(timings[opcode], fetchdat, bit8); + prev_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); + if (prev_regmask & IMPL_ESP) + prev_regmask |= SRCDEP_ESP | DSTDEP_ESP; + prev_deps = deps; + prev_fetchdat = fetchdat; return; } } diff --git a/src/CPU/codegen_timing_pentium.c b/src/CPU/codegen_timing_pentium.c index ecea3125d..74f4a0f3d 100644 --- a/src/CPU/codegen_timing_pentium.c +++ b/src/CPU/codegen_timing_pentium.c @@ -3,6 +3,7 @@ - FPU/FXCH pairing - Prefix decode delay (including shadowing) - FPU latencies + - AGI stalls Elements not taken into account : - Branch prediction (beyond most simplistic approximation) - PMMX decode queue @@ -16,6 +17,8 @@ #include "x87.h" #include "../mem.h" #include "codegen.h" +#include "codegen_ops.h" +#include "codegen_timing_common.h" @@ -51,10 +54,6 @@ static int pair_timings[4][4] = #define CYCLES_MASK ((1ull << 7) - 1) -/*Instruction is MMX shift or pack/unpack instruction*/ -#define MMX_SHIFTPACK (1ull << 7) -/*Instruction is MMX multiply instruction*/ -#define MMX_MULTIPLY (1ull << 8) /*Instruction does not pair*/ #define PAIR_NP (0ull << 29) @@ -73,62 +72,6 @@ static int pair_timings[4][4] = #define PAIR_MASK (7ull << 29) -/*Instruction has input dependency on register in REG field*/ -#define SRCDEP_REG (1ull << 9) -/*Instruction has input dependency on register in R/M field*/ -#define SRCDEP_RM (1ull << 10) -/*Instruction modifies register in REG field*/ -#define DSTDEP_REG (1ull << 11) -/*Instruction modifies register in R/M field*/ -#define DSTDEP_RM (1ull << 12) - -/*Instruction has input dependency on given register*/ -#define SRCDEP_EAX (1ull << 13) -#define SRCDEP_ECX (1ull << 14) -#define SRCDEP_EDX (1ull << 15) -#define SRCDEP_EBX (1ull << 16) -#define SRCDEP_ESP (1ull << 17) -#define SRCDEP_EBP (1ull << 18) -#define SRCDEP_ESI (1ull << 19) -#define SRCDEP_EDI (1ull << 20) - -/*Instruction modifies given register*/ -#define DSTDEP_EAX (1ull << 21) -#define DSTDEP_ECX (1ull << 22) -#define DSTDEP_EDX (1ull << 23) -#define DSTDEP_EBX (1ull << 24) -#define DSTDEP_ESP (1ull << 25) -#define DSTDEP_EBP (1ull << 26) -#define DSTDEP_ESI (1ull << 27) -#define DSTDEP_EDI (1ull << 28) - -/*Instruction pops the FPU stack*/ -#define FPU_POP (1ull << 32) -/*Instruction pops the FPU stack twice*/ -#define FPU_POP2 (1ull << 33) -/*Instruction pushes onto the FPU stack*/ -#define FPU_PUSH (1ull << 34) - -/*Instruction writes to ST(0)*/ -#define FPU_WRITE_ST0 (1ull << 35) -/*Instruction reads from ST(0)*/ -#define FPU_READ_ST0 (1ull << 36) -/*Instruction reads from and writes to ST(0)*/ -#define FPU_RW_ST0 (3ull << 35) - -/*Instruction reads from ST(1)*/ -#define FPU_READ_ST1 (1ull << 37) -/*Instruction writes to ST(1)*/ -#define FPU_WRITE_ST1 (1ull << 38) -/*Instruction reads from and writes to ST(1)*/ -#define FPU_RW_ST1 (3ull << 37) - -/*Instruction reads from ST(reg)*/ -#define FPU_READ_STREG (1ull << 39) -/*Instruction writes to ST(reg)*/ -#define FPU_WRITE_STREG (1ull << 40) -/*Instruction reads from and writes to ST(reg)*/ -#define FPU_RW_STREG (3ull << 39) /*comp_time = cycles until instruction complete i_overlap = cycles that overlap with integer @@ -145,7 +88,6 @@ static int pair_timings[4][4] = #define FPU_RESULT_LATENCY(timing) ((timing >> 41) & 0xff) -#define FPU_FXCH (1ull << 56) #define INVALID 0 @@ -156,119 +98,70 @@ static uint32_t u_pipe_op_32; static uint32_t u_pipe_regmask; static uint32_t u_pipe_fetchdat; static int u_pipe_decode_delay_offset; +static uint64_t *u_pipe_deps; + +static uint32_t regmask_modified; + +static uint32_t addr_regmask; static int fpu_latency; static int fpu_st_latency[8]; -#define REGMASK_SHIFTPACK (1 << 8) -#define REGMASK_MULTIPLY (1 << 8) - -static uint32_t get_srcdep_mask(uint32_t data, uint32_t fetchdat, int bit8) -{ - uint32_t mask = 0; - if (data & SRCDEP_REG) - { - int reg = (fetchdat >> 3) & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - if (data & SRCDEP_RM) - { - int reg = fetchdat & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - mask |= ((data >> 16) & 0xff); - if (data & MMX_SHIFTPACK) - mask |= REGMASK_SHIFTPACK; - if (data & MMX_MULTIPLY) - mask |= REGMASK_MULTIPLY; - - return mask; -} - -static uint32_t get_dstdep_mask(uint32_t data, uint32_t fetchdat, int bit8) -{ - uint32_t mask = 0; - if (data & DSTDEP_REG) - { - int reg = (fetchdat >> 3) & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - if (data & DSTDEP_RM) - { - int reg = fetchdat & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - mask |= ((data >> 24) & 0xff); - if (data & MMX_SHIFTPACK) - mask |= REGMASK_SHIFTPACK; - if (data & MMX_MULTIPLY) - mask |= REGMASK_MULTIPLY; - - return mask; -} static uint64_t opcode_timings[256] = { -/* ADD ADD ADD ADD*/ -/*00*/ PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* ADD ADD PUSH ES POP ES*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* OR OR OR OR*/ - PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* OR OR PUSH CS */ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), INVALID, +/* ADD ADD ADD ADD*/ +/*00*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, +/* ADD ADD PUSH ES POP ES*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* OR OR OR OR*/ + PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, +/* OR OR PUSH CS */ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(1), INVALID, -/* ADC ADC ADC ADC*/ -/*10*/ PAIR_U | CYCLES_RMW | SRCDEP_REG, PAIR_U | CYCLES_RMW | SRCDEP_REG, PAIR_U | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_U | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* ADC ADC PUSH SS POP SS*/ - PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ - PAIR_U | CYCLES_RMW | SRCDEP_REG, PAIR_U | CYCLES_RMW | SRCDEP_REG, PAIR_U | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_U | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* SBB SBB PUSH DS POP DS*/ - PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* ADC ADC ADC ADC*/ +/*10*/ PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, +/* ADC ADC PUSH SS POP SS*/ + PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* SBB SBB SBB SBB*/ + PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, +/* SBB SBB PUSH DS POP DS*/ + PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* AND AND AND AND*/ -/*20*/ PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* AND AND DAA*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), -/* SUB SUB SUB SUB*/ - PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* SUB SUB DAS*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), +/* AND AND AND AND*/ +/*20*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, +/* AND AND DAA*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), +/* SUB SUB SUB SUB*/ + PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, +/* SUB SUB DAS*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), -/* XOR XOR XOR XOR*/ -/*30*/ PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RMW | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG | DSTDEP_REG, -/* XOR XOR AAA*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), -/* CMP CMP CMP CMP*/ - PAIR_UV | CYCLES_RM | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG, -/* CMP CMP AAS*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, INVALID, PAIR_NP | CYCLES(3), +/* XOR XOR XOR XOR*/ +/*30*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, +/* XOR XOR AAA*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), +/* CMP CMP CMP CMP*/ + PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, +/* CMP CMP AAS*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), -/* INC EAX INC ECX INC EDX INC EBX*/ -/*40*/ PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* INC ESP INC EBP INC ESI INC EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, -/* DEC EAX DEC ECX DEC EDX DEC EBX*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* DEC ESP DEC EBP DEC ESI DEC EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* INC ESP INC EBP INC ESI INC EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, -/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ -/*50*/ PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, -/* POP EAX POP ECX POP EDX POP EBX*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* POP ESP POP EBP POP ESI POP EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* POP EAX POP ECX POP EDX POP EBX*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* POP ESP POP EBP POP ESI POP EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* PUSHA POPA BOUND ARPL*/ /*60*/ PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(8), PAIR_NP | CYCLES(7), @@ -284,13 +177,13 @@ static uint64_t opcode_timings[256] = PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, -/*80*/ INVALID, INVALID, INVALID, INVALID, -/* TEST TEST XCHG XCHG*/ - PAIR_UV | CYCLES_RM | SRCDEP_REG, PAIR_UV | CYCLES_RM | SRCDEP_REG, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), -/* MOV MOV MOV MOV*/ - PAIR_UV | CYCLES_REG | SRCDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG, PAIR_UV | CYCLES_REG | DSTDEP_REG, PAIR_UV | CYCLES_REG | DSTDEP_REG, -/* MOV from seg LEA MOV to seg POP*/ - PAIR_NP | CYCLES(1), PAIR_UV | CYCLES_REG | DSTDEP_REG, CYCLES(3), PAIR_NP | CYCLES(3), +/*80*/ INVALID, INVALID, INVALID, INVALID, +/* TEST TEST XCHG XCHG*/ + PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), +/* MOV MOV MOV MOV*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV, +/* MOV from seg LEA MOV to seg POP*/ + PAIR_NP | CYCLES(1), PAIR_UV | CYCLES_REG, CYCLES(3), PAIR_NP | CYCLES(3), /* NOP XCHG XCHG XCHG*/ /*90*/ PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), @@ -302,19 +195,19 @@ static uint64_t opcode_timings[256] = PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), /* MOV MOV MOV MOV*/ -/*a0*/ PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, +/*a0*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* MOVSB MOVSW CMPSB CMPSW*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), /* TEST TEST STOSB STOSW*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* LODSB LODSW SCASB SCASW*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), /* MOV*/ -/*b0*/ PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_ECX, PAIR_UV | CYCLES_REG | DSTDEP_EDX, PAIR_UV | CYCLES_REG | DSTDEP_EBX, - PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_ECX, PAIR_UV | CYCLES_REG | DSTDEP_EDX, PAIR_UV | CYCLES_REG | DSTDEP_EBX, - PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_ECX, PAIR_UV | CYCLES_REG | DSTDEP_EDX, PAIR_UV | CYCLES_REG | DSTDEP_EBX, - PAIR_UV | CYCLES_REG | DSTDEP_ESP, PAIR_UV | CYCLES_REG | DSTDEP_EBP, PAIR_UV | CYCLES_REG | DSTDEP_ESI, PAIR_UV | CYCLES_REG | DSTDEP_EDI, +/*b0*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* RET imm RET*/ /*c0*/ INVALID, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(2), @@ -352,59 +245,59 @@ static uint64_t opcode_timings[256] = static uint64_t opcode_timings_mod3[256] = { -/* ADD ADD ADD ADD*/ -/*00*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* ADD ADD PUSH ES POP ES*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* OR OR OR OR*/ - PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* OR OR PUSH CS */ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), INVALID, +/* ADD ADD ADD ADD*/ +/*00*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* ADD ADD PUSH ES POP ES*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* OR OR OR OR*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* OR OR PUSH CS */ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(1), INVALID, -/* ADC ADC ADC ADC*/ -/*10*/ PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* ADC ADC PUSH SS POP SS*/ - PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ - PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_U | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* SBB SBB PUSH DS POP DS*/ - PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_U | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* ADC ADC ADC ADC*/ +/*10*/ PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, +/* ADC ADC PUSH SS POP SS*/ + PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), +/* SBB SBB SBB SBB*/ + PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, +/* SBB SBB PUSH DS POP DS*/ + PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* AND AND AND AND*/ -/*20*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* AND AND DAA*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), -/* SUB SUB SUB SUB*/ - PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* SUB SUB DAS*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), +/* AND AND AND AND*/ +/*20*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* AND AND DAA*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), +/* SUB SUB SUB SUB*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* SUB SUB DAS*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), -/* XOR XOR XOR XOR*/ -/*30*/ PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM | DSTDEP_REG, -/* XOR XOR AAA*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, INVALID, PAIR_NP | CYCLES(3), -/* CMP CMP CMP CMP*/ - PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_RM | SRCDEP_REG, -/* CMP CMP AAS*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, INVALID, PAIR_NP | CYCLES(3), +/* XOR XOR XOR XOR*/ +/*30*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* XOR XOR AAA*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), +/* CMP CMP CMP CMP*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* CMP CMP AAS*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), -/* INC EAX INC ECX INC EDX INC EBX*/ -/*40*/ PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* INC ESP INC EBP INC ESI INC EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, -/* DEC EAX DEC ECX DEC EDX DEC EBX*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* DEC ESP DEC EBP DEC ESI DEC EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* INC ESP INC EBP INC ESI INC EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, -/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ -/*50*/ PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, -/* POP EAX POP ECX POP EDX POP EBX*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_ECX | DSTDEP_ECX, PAIR_UV | CYCLES_REG | SRCDEP_EDX | DSTDEP_EDX, PAIR_UV | CYCLES_REG | SRCDEP_EBX | DSTDEP_EBX, -/* POP ESP POP EBP POP ESI POP EDI*/ - PAIR_UV | CYCLES_REG | SRCDEP_ESP | DSTDEP_ESP, PAIR_UV | CYCLES_REG | SRCDEP_EBP | DSTDEP_EBP, PAIR_UV | CYCLES_REG | SRCDEP_ESI | DSTDEP_ESI, PAIR_UV | CYCLES_REG | SRCDEP_EDI | DSTDEP_EDI, +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* POP EAX POP ECX POP EDX POP EBX*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* POP ESP POP EBP POP ESI POP EDI*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* PUSHA POPA BOUND ARPL*/ /*60*/ PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(8), PAIR_NP | CYCLES(7), @@ -420,13 +313,13 @@ static uint64_t opcode_timings_mod3[256] = PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, -/*80*/ PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, -/* TEST TEST XCHG XCHG*/ - PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_REG | SRCDEP_RM, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), -/* MOV MOV MOV MOV*/ - PAIR_UV | CYCLES_REG | SRCDEP_REG | DSTDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_REG | DSTDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_REG, PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_REG, -/* MOV from seg LEA MOV to seg POP*/ - PAIR_NP | CYCLES(1), PAIR_UV | CYCLES_REG | DSTDEP_REG, CYCLES(3), PAIR_NP | CYCLES(3), +/*80*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* TEST TEST XCHG XCHG*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), +/* MOV MOV MOV MOV*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/* MOV from seg LEA MOV to seg POP*/ + PAIR_NP | CYCLES(1), PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* NOP XCHG XCHG XCHG*/ /*90*/ PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), @@ -438,19 +331,19 @@ static uint64_t opcode_timings_mod3[256] = PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), /* MOV MOV MOV MOV*/ -/*a0*/ PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, +/*a0*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* MOVSB MOVSW CMPSB CMPSW*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), /* TEST TEST STOSB STOSW*/ - PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_UV | CYCLES_REG | SRCDEP_EAX, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* LODSB LODSW SCASB SCASW*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), /* MOV*/ -/*b0*/ PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_ECX, PAIR_UV | CYCLES_REG | DSTDEP_EDX, PAIR_UV | CYCLES_REG | DSTDEP_EBX, - PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_ECX, PAIR_UV | CYCLES_REG | DSTDEP_EDX, PAIR_UV | CYCLES_REG | DSTDEP_EBX, - PAIR_UV | CYCLES_REG | DSTDEP_EAX, PAIR_UV | CYCLES_REG | DSTDEP_ECX, PAIR_UV | CYCLES_REG | DSTDEP_EDX, PAIR_UV | CYCLES_REG | DSTDEP_EBX, - PAIR_UV | CYCLES_REG | DSTDEP_ESP, PAIR_UV | CYCLES_REG | DSTDEP_EBP, PAIR_UV | CYCLES_REG | DSTDEP_ESI, PAIR_UV | CYCLES_REG | DSTDEP_EDI, +/*b0*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* RET imm RET*/ /*c0*/ INVALID, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(2), @@ -489,20 +382,20 @@ static uint64_t opcode_timings_mod3[256] = static uint64_t opcode_timings_0f[256] = { -/*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), - INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, - PAIR_NP | CYCLES(1000), PAIR_NP | CYCLES(10000), INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, +/*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), + INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, + PAIR_NP | CYCLES(1000), PAIR_NP | CYCLES(10000), INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, /*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, -/*20*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), - PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, +/*20*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), + PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, /*30*/ PAIR_NP | CYCLES(9), CYCLES(1), PAIR_NP | CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, @@ -519,15 +412,15 @@ static uint64_t opcode_timings_0f[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, -/*60*/ PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, - PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, - INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, +/*60*/ PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, + INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, -/*70*/ INVALID, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_NP | CYCLES(100), - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, +/*70*/ INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_NP | CYCLES(100), + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, /*80*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), @@ -554,20 +447,20 @@ static uint64_t opcode_timings_0f[256] = PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), -/*d0*/ INVALID, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, - INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, +/*d0*/ INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, + INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, -/*e0*/ INVALID, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, INVALID, - INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, +/*e0*/ INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, + INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, -/*f0*/ INVALID, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, PAIR_U | MMX_SHIFTPACK | CYCLES_RM, - INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, - PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, +/*f0*/ INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, + INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, + PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, }; static uint64_t opcode_timings_0f_mod3[256] = { @@ -601,15 +494,15 @@ static uint64_t opcode_timings_0f_mod3[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, -/*60*/ PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, - PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, - INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/*60*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, -/*70*/ INVALID, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(100), - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, +/*70*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(100), + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /*80*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), @@ -636,20 +529,20 @@ static uint64_t opcode_timings_0f_mod3[256] = PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), -/*d0*/ INVALID, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, - INVALID, PAIR_UV | MMX_MULTIPLY | CYCLES_REG, INVALID, INVALID, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, +/*d0*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + INVALID, PAIR_UV | CYCLES_REG, INVALID, INVALID, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, -/*e0*/ INVALID, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, INVALID, - INVALID, PAIR_UV | MMX_MULTIPLY | CYCLES_REG, INVALID, INVALID, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, +/*e0*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, + INVALID, PAIR_UV | CYCLES_REG, INVALID, INVALID, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, -/*f0*/ INVALID, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, PAIR_UV | MMX_SHIFTPACK | CYCLES_REG, - INVALID, PAIR_UV | MMX_MULTIPLY | CYCLES_REG, INVALID, INVALID, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, +/*f0*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + INVALID, PAIR_UV | CYCLES_REG, INVALID, INVALID, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, }; static uint64_t opcode_timings_shift[8] = @@ -659,8 +552,8 @@ static uint64_t opcode_timings_shift[8] = }; static uint64_t opcode_timings_shift_mod3[8] = { - PAIR_U | CYCLES_REG | DSTDEP_RM, PAIR_U | CYCLES_REG | DSTDEP_RM, PAIR_U | CYCLES_REG | DSTDEP_RM, PAIR_U | CYCLES_REG | DSTDEP_RM, - PAIR_U | CYCLES_REG | DSTDEP_RM, PAIR_U | CYCLES_REG | DSTDEP_RM, PAIR_U | CYCLES_REG | DSTDEP_RM, PAIR_U | CYCLES_REG | DSTDEP_RM, + PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, + PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, }; static uint64_t opcode_timings_f6[8] = @@ -673,83 +566,83 @@ static uint64_t opcode_timings_f6[8] = static uint64_t opcode_timings_f6_mod3[8] = { /* TST NOT NEG*/ - PAIR_UV | CYCLES_REG | SRCDEP_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), + PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(17), PAIR_NP | CYCLES(22) }; static uint64_t opcode_timings_f7[8] = { -/* TST NOT NEG*/ - PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), -/* MUL IMUL DIV IDIV*/ - PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) +/* TST NOT NEG*/ + PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), +/* MUL IMUL DIV IDIV*/ + PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) }; static uint64_t opcode_timings_f7_mod3[8] = { -/* TST NOT NEG*/ - PAIR_UV | CYCLES_REG | SRCDEP_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), -/* MUL IMUL DIV IDIV*/ - PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) +/* TST NOT NEG*/ + PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), +/* MUL IMUL DIV IDIV*/ + PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) }; static uint64_t opcode_timings_ff[8] = { -/* INC DEC CALL CALL far*/ - PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), +/* INC DEC CALL CALL far*/ + PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), /* JMP JMP far PUSH*/ - PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID + PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID }; static uint64_t opcode_timings_ff_mod3[8] = { -/* INC DEC CALL CALL far*/ - PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_UV | CYCLES_REG | SRCDEP_RM | DSTDEP_RM, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), +/* INC DEC CALL CALL far*/ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), /* JMP JMP far PUSH*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID }; static uint64_t opcode_timings_d8[8] = { -/* FADDs FMULs FCOMs FCOMPs*/ - PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_CYCLES(1,0,0), PAIR_FX | FPU_POP | FPU_READ_ST0 | FPU_CYCLES(1,0,0), -/* FSUBs FSUBRs FDIVs FDIVRs*/ - PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(39,38,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(39,38,2) +/* FADDs FMULs FCOMs FCOMPs*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), +/* FSUBs FSUBRs FDIVs FDIVRs*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; static uint64_t opcode_timings_d8_mod3[8] = { -/* FADD FMUL FCOM FCOMP*/ - PAIR_FX | FPU_RW_ST0 | FPU_READ_STREG | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_READ_STREG | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_FX | FPU_POP | FPU_READ_ST0 | FPU_READ_STREG | FPU_CYCLES(1,0,0), -/* FSUB FSUBR FDIV FDIVR*/ - PAIR_FX | FPU_RW_ST0 | FPU_READ_STREG | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_READ_STREG | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_READ_STREG | FPU_CYCLES(39,38,2), PAIR_FX | FPU_RW_ST0 | FPU_READ_STREG | FPU_CYCLES(39,38,2) +/* FADD FMUL FCOM FCOMP*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), +/* FSUB FSUBR FDIV FDIVR*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; static uint64_t opcode_timings_d9[8] = { -/* FLDs FSTs FSTPs*/ - PAIR_FX | FPU_PUSH | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_READ_ST0 | FPU_CYCLES(2,0,0), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(2,0,0), -/* FLDENV FLDCW FSTENV FSTCW*/ - PAIR_NP | FPU_CYCLES(32,0,0), PAIR_NP | FPU_CYCLES(8,0,0), PAIR_NP | FPU_CYCLES(48,0,0), PAIR_NP | FPU_CYCLES(2,0,0) +/* FLDs FSTs FSTPs*/ + PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), +/* FLDENV FLDCW FSTENV FSTCW*/ + PAIR_NP | FPU_CYCLES(32,0,0), PAIR_NP | FPU_CYCLES(8,0,0), PAIR_NP | FPU_CYCLES(48,0,0), PAIR_NP | FPU_CYCLES(2,0,0) }; static uint64_t opcode_timings_d9_mod3[64] = { /*FLD*/ - PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), - PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_FX | FPU_PUSH | FPU_READ_STREG | FPU_CYCLES(1,0,0), + PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), + PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), /*FXCH*/ - PAIR_FXCH | FPU_FXCH | CYCLES(0), PAIR_FXCH | FPU_FXCH | CYCLES(0), PAIR_FXCH | FPU_FXCH | CYCLES(0), PAIR_FXCH | FPU_FXCH | CYCLES(0), - PAIR_FXCH | FPU_FXCH | CYCLES(0), PAIR_FXCH | FPU_FXCH | CYCLES(0), PAIR_FXCH | FPU_FXCH | CYCLES(0), PAIR_FXCH | FPU_FXCH | CYCLES(0), + PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), + PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), /*FNOP*/ PAIR_NP | FPU_CYCLES(3,0,0), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /*FSTP*/ - PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), - PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), + PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), + PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), /* opFCHS opFABS*/ PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), INVALID, INVALID, /* opFTST opFXAM*/ PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(21,4,0), INVALID, INVALID, /* opFLD1 opFLDL2T opFLDL2E opFLDPI*/ - PAIR_NP | FPU_PUSH | FPU_CYCLES(2,0,0), PAIR_NP | FPU_PUSH | FPU_CYCLES(5,2,2), PAIR_NP | FPU_PUSH | FPU_CYCLES(5,2,2), PAIR_NP | FPU_PUSH | FPU_CYCLES(5,2,2), + PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(5,2,2), PAIR_NP | FPU_CYCLES(5,2,2), PAIR_NP | FPU_CYCLES(5,2,2), /* opFLDEG2 opFLDLN2 opFLDZ*/ - PAIR_NP | FPU_PUSH | FPU_CYCLES(5,2,2), PAIR_NP | FPU_PUSH | FPU_CYCLES(5,2,2), PAIR_NP | FPU_PUSH | FPU_CYCLES(2,0,0), INVALID, + PAIR_NP | FPU_CYCLES(5,2,2), PAIR_NP | FPU_CYCLES(5,2,2), PAIR_NP | FPU_CYCLES(2,0,0), INVALID, /* opF2XM1 opFYL2X opFPTAN opFPATAN*/ PAIR_NP | FPU_CYCLES(53,2,2), PAIR_NP | FPU_CYCLES(103,2,2), PAIR_NP | FPU_CYCLES(120,36,0), PAIR_NP | FPU_CYCLES(112,2,2), /* opFDECSTP opFINCSTP,*/ @@ -762,25 +655,25 @@ static uint64_t opcode_timings_d9_mod3[64] = static uint64_t opcode_timings_da[8] = { -/* FIADDl FIMULl FICOMl FICOMPl*/ - PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_READ_ST0 | FPU_CYCLES(4,0,0), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(4,0,0), -/* FISUBl FISUBRl FIDIVl FIDIVRl*/ - PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(42,38,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(42,38,2) +/* FIADDl FIMULl FICOMl FICOMPl*/ + PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), +/* FISUBl FISUBRl FIDIVl FIDIVRl*/ + PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) }; static uint64_t opcode_timings_da_mod3[8] = { - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ - INVALID, PAIR_NP | FPU_POP2 | FPU_CYCLES(1,0,0), INVALID, INVALID + INVALID, PAIR_NP | FPU_CYCLES(1,0,0), INVALID, INVALID }; static uint64_t opcode_timings_db[8] = { -/* FLDil FSTil FSTPil*/ - PAIR_NP | FPU_PUSH | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_READ_ST0 | FPU_CYCLES(6,0,0), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(6,0,0), -/* FLDe FSTPe*/ - INVALID, PAIR_NP | FPU_PUSH | FPU_CYCLES(3,0,0), INVALID, PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(3,0,0) +/* FLDil FSTil FSTPil*/ + PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), +/* FLDe FSTPe*/ + INVALID, PAIR_NP | FPU_CYCLES(3,0,0), INVALID, PAIR_NP | FPU_CYCLES(3,0,0) }; static uint64_t opcode_timings_db_mod3[64] = { @@ -813,55 +706,55 @@ static uint64_t opcode_timings_db_mod3[64] = static uint64_t opcode_timings_dc[8] = { -/* FADDd FMULd FCOMd FCOMPd*/ - PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_CYCLES(1,0,0), PAIR_FX | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(1,0,0), -/* FSUBd FSUBRd FDIVd FDIVRd*/ - PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(3,2,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(39,38,2), PAIR_FX | FPU_RW_ST0 | FPU_CYCLES(39,38,2) +/* FADDd FMULd FCOMd FCOMPd*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), +/* FSUBd FSUBRd FDIVd FDIVRd*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; static uint64_t opcode_timings_dc_mod3[8] = { -/* opFADDr opFMULr*/ - PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_CYCLES(3,2,2), INVALID, INVALID, -/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ - PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_CYCLES(39,38,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_CYCLES(39,38,2) +/* opFADDr opFMULr*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, INVALID, +/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; static uint64_t opcode_timings_dd[8] = { -/* FLDd FSTd FSTPd*/ - PAIR_FX | FPU_PUSH | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_READ_ST0 | FPU_CYCLES(2,0,0), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(2,0,0), -/* FRSTOR FSAVE FSTSW*/ - PAIR_NP | FPU_CYCLES(70,0,0), INVALID, PAIR_NP | FPU_CYCLES(127,0,0), PAIR_NP | FPU_CYCLES(6,0,0) +/* FLDd FSTd FSTPd*/ + PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), +/* FRSTOR FSAVE FSTSW*/ + PAIR_NP | FPU_CYCLES(70,0,0), INVALID, PAIR_NP | FPU_CYCLES(127,0,0), PAIR_NP | FPU_CYCLES(6,0,0) }; static uint64_t opcode_timings_dd_mod3[8] = { -/* FFFREE FST FSTP*/ - PAIR_NP | FPU_CYCLES(2,0,0), INVALID, PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP | FPU_CYCLES(1,0,0), -/* FUCOM FUCOMP*/ - PAIR_NP | FPU_READ_ST0 | FPU_READ_STREG | FPU_CYCLES(1,0,0), PAIR_NP | FPU_READ_ST0 | FPU_READ_STREG | FPU_POP | FPU_CYCLES(1,0,0), INVALID, INVALID +/* FFFREE FST FSTP*/ + PAIR_NP | FPU_CYCLES(2,0,0), INVALID, PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), +/* FUCOM FUCOMP*/ + PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), INVALID, INVALID }; static uint64_t opcode_timings_de[8] = { -/* FIADDw FIMULw FICOMw FICOMPw*/ - PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_READ_ST0 | FPU_CYCLES(4,0,0), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(4,0,0), -/* FISUBw FISUBRw FIDIVw FIDIVRw*/ - PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(6,2,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(42,38,2), PAIR_NP | FPU_RW_ST0 | FPU_CYCLES(42,38,2) +/* FIADDw FIMULw FICOMw FICOMPw*/ + PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), +/* FISUBw FISUBRw FIDIVw FIDIVRw*/ + PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) }; static uint64_t opcode_timings_de_mod3[8] = { -/* FADDP FMULP FCOMPP*/ - PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_POP | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_POP | FPU_CYCLES(3,2,2), INVALID, PAIR_FX | FPU_READ_ST0 | FPU_READ_ST1 | FPU_POP2 | FPU_CYCLES(1,0,0), -/* FSUBP FSUBRP FDIVP FDIVRP*/ - PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_POP | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_POP | FPU_CYCLES(3,2,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_POP | FPU_CYCLES(39,38,2), PAIR_FX | FPU_READ_ST0 | FPU_RW_STREG | FPU_POP | FPU_CYCLES(39,38,2) +/* FADDP FMULP FCOMPP*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, PAIR_FX | FPU_CYCLES(1,0,0), +/* FSUBP FSUBRP FDIVP FDIVRP*/ + PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; static uint64_t opcode_timings_df[8] = { -/* FILDiw FISTiw FISTPiw*/ - PAIR_NP | FPU_PUSH | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_READ_ST0 | FPU_CYCLES(6,0,0), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(6,0,0), -/* FILDiq FBSTP FISTPiq*/ - INVALID, PAIR_NP | FPU_PUSH | FPU_CYCLES(3,2,2), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(148,0,0), PAIR_NP | FPU_READ_ST0 | FPU_POP | FPU_CYCLES(6,0,0) +/* FILDiw FISTiw FISTPiw*/ + PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), +/* FILDiq FBSTP FISTPiq*/ + INVALID, PAIR_NP | FPU_CYCLES(3,2,2), PAIR_NP | FPU_CYCLES(148,0,0), PAIR_NP | FPU_CYCLES(6,0,0) }; static uint64_t opcode_timings_df_mod3[8] = { @@ -872,38 +765,48 @@ static uint64_t opcode_timings_df_mod3[8] = static uint64_t opcode_timings_81[8] = { - PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, - PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM1632, PAIR_UV | CYCLES_RM | SRCDEP_REG | CYCLES_IMM1632 + PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, + PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RM | CYCLES_IMM1632 +}; +static uint64_t opcode_timings_81_mod3[8] = +{ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG }; static uint64_t opcode_timings_8x[8] = { - PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, - PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | SRCDEP_REG | CYCLES_IMM8, PAIR_UV | CYCLES_RM | SRCDEP_REG | CYCLES_IMM8 + PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, + PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RM | CYCLES_IMM8 +}; +static uint64_t opcode_timings_8x_mod3[8] = +{ + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG }; static int decode_delay, decode_delay_offset; static uint8_t last_prefix; static int prefixes; -static inline int COUNT(uint64_t c, int op_32) +static inline int COUNT(uint64_t timings, uint64_t deps, int op_32) { - if ((c & PAIR_FPU) && !(c & FPU_FXCH)) - return FPU_I_LATENCY(c); - if (c & CYCLES_HAS_MULTI) + if ((timings & PAIR_FPU) && !(deps & FPU_FXCH)) + return FPU_I_LATENCY(timings); + if (timings & CYCLES_HAS_MULTI) { if (op_32 & 0x100) - return ((uintptr_t)c >> 8) & 0xff; - return (uintptr_t)c & 0xff; + return ((uintptr_t)timings >> 8) & 0xff; + return (uintptr_t)timings & 0xff; } - if (!(c & PAIR_MASK)) - return c & 0xffff; - if ((c & PAIR_MASK) == PAIR_FX) - return c & 0xffff; - if ((c & PAIR_MASK) == PAIR_FXCH) - return c & 0xffff; - if ((c & PAIR_UV) && !(c & PAIR_FPU)) - c &= 3; - switch (c & CYCLES_MASK) + if (!(timings & PAIR_MASK)) + return timings & 0xffff; + if ((timings & PAIR_MASK) == PAIR_FX) + return timings & 0xffff; + if ((timings & PAIR_MASK) == PAIR_FXCH) + return timings & 0xffff; + if ((timings & PAIR_UV) && !(timings & PAIR_FPU)) + timings &= 3; + switch (timings & CYCLES_MASK) { case CYCLES_REG: return 1; @@ -915,20 +818,20 @@ static inline int COUNT(uint64_t c, int op_32) return cpu_hasMMX ? 1 : 2; } - fatal("Illegal COUNT %016llx\n", c); + fatal("Illegal COUNT %016llx\n", timings); - return c; + return timings; } -static int codegen_fpu_latencies(uint64_t timings, int reg) +static int codegen_fpu_latencies(uint64_t deps, int reg) { int latency = fpu_latency; - if ((timings & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency) + if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency) latency = fpu_st_latency[0]; - if ((timings & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency) + if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency) latency = fpu_st_latency[1]; - if ((timings & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency) + if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency) latency = fpu_st_latency[reg]; return latency; @@ -1070,14 +973,32 @@ void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; } -static void codegen_instruction(uint64_t *timings, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32) +static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) +{ + uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); + + /*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not + cause AGIs with each other, but do with instructions that use it explicitly*/ + if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP)) + addr_regmask |= (1 << REG_ESP); + + return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP; +} + +static void codegen_instruction(uint64_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) { int instr_cycles, latency = 0; - if ((timings[opcode] & PAIR_FPU) && !(timings[opcode] & FPU_FXCH)) - instr_cycles = latency = codegen_fpu_latencies(timings[opcode], fetchdat & 7); + if ((timings[opcode] & PAIR_FPU) && !(deps[opcode] & FPU_FXCH)) + instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7); else { +/* if (timings[opcode] & FPU_WRITE_ST0) + fatal("FPU_WRITE_ST0\n"); + if (timings[opcode] & FPU_WRITE_ST1) + fatal("FPU_WRITE_ST1\n"); + if (timings[opcode] & FPU_WRITE_STREG) + fatal("FPU_WRITE_STREG\n");*/ instr_cycles = 0; } @@ -1085,14 +1006,16 @@ static void codegen_instruction(uint64_t *timings, uint8_t opcode, uint32_t fetc codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles); else codegen_fpu_latency_clock(instr_cycles); - instr_cycles += COUNT(timings[opcode], op_32); + instr_cycles += COUNT(timings[opcode], deps[opcode], op_32); + instr_cycles += exec_delay; if ((decode_delay + decode_delay_offset) > 0) codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset; else codegen_block_cycles += instr_cycles; + decode_delay = (-instr_cycles) + 1; - if (timings[opcode] & FPU_POP) + if (deps[opcode] & FPU_POP) { int c; @@ -1100,7 +1023,7 @@ static void codegen_instruction(uint64_t *timings, uint8_t opcode, uint32_t fetc fpu_st_latency[c] = fpu_st_latency[c+1]; fpu_st_latency[7] = 0; } - if (timings[opcode] & FPU_POP2) + if (deps[opcode] & FPU_POP2) { int c; @@ -1108,12 +1031,14 @@ static void codegen_instruction(uint64_t *timings, uint8_t opcode, uint32_t fetc fpu_st_latency[c] = fpu_st_latency[c+2]; fpu_st_latency[6] = fpu_st_latency[7] = 0; } - if ((timings[opcode] & PAIR_FPU) && !(timings[opcode] & FPU_FXCH)) + if ((timings[opcode] & PAIR_FPU) && !(deps[opcode] & FPU_FXCH)) { + /* if (fpu_latency) + fatal("Bad latency FPU\n");*/ fpu_latency = FPU_F_LATENCY(timings[opcode]); } - if (timings[opcode] & FPU_PUSH) + if (deps[opcode] & FPU_PUSH) { int c; @@ -1121,23 +1046,29 @@ static void codegen_instruction(uint64_t *timings, uint8_t opcode, uint32_t fetc fpu_st_latency[c+1] = fpu_st_latency[c]; fpu_st_latency[0] = 0; } - if (timings[opcode] & FPU_WRITE_ST0) + if (deps[opcode] & FPU_WRITE_ST0) { +/* if (fpu_st_latency[0]) + fatal("Bad latency ST0\n");*/ fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]); } - if (timings[opcode] & FPU_WRITE_ST1) + if (deps[opcode] & FPU_WRITE_ST1) { +/* if (fpu_st_latency[1]) + fatal("Bad latency ST1\n");*/ fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]); } - if (timings[opcode] & FPU_WRITE_STREG) + if (deps[opcode] & FPU_WRITE_STREG) { int reg = fetchdat & 7; - if (timings[opcode] & FPU_POP) + if (deps[opcode] & FPU_POP) reg--; if (reg >= 0 && - !(reg == 0 && (timings[opcode] & FPU_WRITE_ST0)) && - !(reg == 1 && (timings[opcode] & FPU_WRITE_ST1))) + !(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) && + !(reg == 1 && (deps[opcode] & FPU_WRITE_ST1))) { +/* if (fpu_st_latency[reg]) + fatal("Bad latency STREG %i %08x %i %016llx %02x\n",fpu_st_latency[reg], fetchdat, reg, timings[opcode], opcode);*/ fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]); } } @@ -1146,45 +1077,56 @@ static void codegen_instruction(uint64_t *timings, uint8_t opcode, uint32_t fetc void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { uint64_t *timings; + uint64_t *deps; int mod3 = ((fetchdat & 0xc0) == 0xc0); int bit8 = !(opcode & 1); + int agi_stall = 0; switch (last_prefix) { case 0x0f: timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -1192,44 +1134,55 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) switch (opcode) { case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_mod3 : opcode_timings_8x; - if (!mod3) - opcode = (fetchdat >> 3) & 7; + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + opcode = (fetchdat >> 3) & 7; break; case 0x81: - timings = mod3 ? opcode_timings_mod3 : opcode_timings_81; - if (!mod3) - opcode = (fetchdat >> 3) & 7; + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; break; - case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xc0: case 0xc1: case 0xd0: case 0xd1: timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xd2: case 0xd3: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; opcode = (fetchdat >> 3) & 7; break; case 0xf6: timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } } if (u_pipe_full) { - uint8_t regmask = get_srcdep_mask(timings[opcode], fetchdat, bit8); - + uint8_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, u_pipe_op_32); + if ((u_pipe_timings[u_pipe_opcode] & PAIR_MASK) == PAIR_FX && (timings[opcode] & PAIR_MASK) != PAIR_FXCH) goto nopair; @@ -1243,7 +1196,10 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { int temp; - codegen_instruction(u_pipe_timings, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32); + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); temp = fpu_st_latency[fetchdat & 7]; fpu_st_latency[fetchdat & 7] = fpu_st_latency[0]; @@ -1251,6 +1207,8 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) u_pipe_full = 0; decode_delay_offset = 0; + regmask_modified = u_pipe_regmask; + addr_regmask = 0; return; } @@ -1269,32 +1227,42 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) int t2 = timings[opcode] & CYCLES_MASK; int t_pair; uint64_t temp_timing; + uint64_t temp_deps = 0; if (!(u_pipe_timings[u_pipe_opcode] & PAIR_FPU)) t1 &= 3; if (!(timings[opcode] & PAIR_FPU)) t2 &= 3; - + if (t1 < 0 || t2 < 0 || t1 > CYCLES_BRANCH || t2 > CYCLES_BRANCH) fatal("Pair out of range\n"); t_pair = pair_timings[t1][t2]; if (t_pair < 1) fatal("Illegal pair timings : t1=%i t2=%i u_opcode=%02x v_opcode=%02x\n", t1, t2, u_pipe_opcode, opcode); - + /*Instruction can pair with previous*/ temp_timing = t_pair; - codegen_instruction(&temp_timing, 0, 0, 0, 0); + if (check_agi(deps, opcode, fetchdat, op_32) || check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(&temp_timing, &temp_deps, 0, 0, 0, 0, agi_stall); u_pipe_full = 0; decode_delay_offset = 0; + + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | u_pipe_regmask; + addr_regmask = 0; return; } } nopair: /*Instruction can not pair with previous*/ /*Run previous now*/ - codegen_instruction(u_pipe_timings, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32); + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); u_pipe_full = 0; + regmask_modified = u_pipe_regmask; + addr_regmask = 0; } if ((timings[opcode] & PAIR_U) && (decode_delay + decode_delay_offset) <= 0) @@ -1313,16 +1281,21 @@ nopair: u_pipe_opcode = opcode; u_pipe_timings = timings; u_pipe_op_32 = op_32; - u_pipe_regmask = get_dstdep_mask(timings[opcode], fetchdat, bit8); + u_pipe_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); u_pipe_fetchdat = fetchdat; u_pipe_decode_delay_offset = decode_delay_offset; + u_pipe_deps = deps; decode_delay_offset = 0; return; } } /*Instruction can not pair and must run now*/ - codegen_instruction(timings, opcode, fetchdat, decode_delay_offset, op_32); + if (check_agi(deps, opcode, fetchdat, op_32)) + agi_stall = 1; + codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall); decode_delay_offset = 0; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); + addr_regmask = 0; } void codegen_timing_pentium_block_end() @@ -1330,7 +1303,9 @@ void codegen_timing_pentium_block_end() if (u_pipe_full) { /*Run previous now*/ - codegen_block_cycles += COUNT(u_pipe_timings[u_pipe_opcode], u_pipe_op_32) + decode_delay + decode_delay_offset; + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + codegen_block_cycles++; + codegen_block_cycles += COUNT(u_pipe_timings[u_pipe_opcode], u_pipe_deps[u_pipe_opcode], u_pipe_op_32) + decode_delay + decode_delay_offset; u_pipe_full = 0; } } diff --git a/src/CPU/codegen_timing_winchip.c b/src/CPU/codegen_timing_winchip.c index a76a08e7a..291a5b435 100644 --- a/src/CPU/codegen_timing_winchip.c +++ b/src/CPU/codegen_timing_winchip.c @@ -1,10 +1,12 @@ #include "../ibm.h" -#include "../mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" +#include "../mem.h" #include "codegen.h" +#include "codegen_ops.h" +#include "codegen_timing_common.h" #define CYCLES(c) (int *)c #define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8)) @@ -247,14 +249,27 @@ static int *opcode_timings_8x[8] = { &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm }; +static int *opcode_timings_8x_mod3[8] = +{ + &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm +}; +static int *opcode_timings_81[8] = +{ + &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm +}; +static int *opcode_timings_81_mod3[8] = +{ + &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm +}; static int timing_count; static uint8_t last_prefix; +static uint32_t regmask_modified; -static __inline int COUNT(int *c, int op_32) +static inline int COUNT(int *c, int op_32) { if ((uintptr_t)c <= 10000) - return (int)c; + return (int)(uintptr_t)c; if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff)) { if (op_32 & 0x100) @@ -266,6 +281,7 @@ static __inline int COUNT(int *c, int op_32) void codegen_timing_winchip_block_start() { + regmask_modified = 0; } void codegen_timing_winchip_start() @@ -283,82 +299,107 @@ void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat) void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { int **timings; + uint64_t *deps; int mod3 = ((fetchdat & 0xc0) == 0xc0); + int bit8 = !(opcode & 1); switch (last_prefix) { case 0x0f: timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; default: switch (opcode) { - case 0x80: case 0x81: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_mod3 : opcode_timings_8x; - if (!mod3) - opcode = (fetchdat >> 3) & 7; + case 0x80: case 0x82: case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; break; case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xf6: timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } } timing_count += COUNT(timings[opcode], op_32); + if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32)) + timing_count++; /*AGI stall*/ codegen_block_cycles += timing_count; + + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } void codegen_timing_winchip_block_end() diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 79645cb4c..63bb51fe0 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -146,7 +146,8 @@ MAINOBJ = pc.o config.o device.o timer.o dma.o io.o nmi.o pic.o \ memregs.o intel_flash.o rtc.o nvr.o ps2_nvr.o CPUOBJ = cpu.o 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o \ codegen.o \ - codegen_ops.o codegen_timing_486.o \ + codegen_ops.o \ + codegen_timing_common.o codegen_timing_486.o \ codegen_timing_686.o codegen_timing_pentium.o \ codegen_timing_winchip.o $(PLATCG) \ x86seg.o x87.o diff --git a/src/mouse.c b/src/mouse.c index 1d23821b0..a72030324 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -8,10 +8,11 @@ * * Common driver module for MOUSE devices. * - * Version: @(#)mouse.c 1.0.3 2017/06/21 + * Version: @(#)mouse.c 1.0.4 2017/07/24 * * Authors: Sarah Walker, * Miran Grca, + * TheCollector1995, * Fred N. van Kempen, * Copyright 2008-2017 Sarah Walker. * Copyright 2016-2017 Miran Grca. @@ -36,15 +37,15 @@ static mouse_t mouse_none = { static mouse_t *mouse_list[] = { &mouse_none, &mouse_bus, /* 1 Microsoft/Logitech Bus Mouse 2-button */ - &mouse_msystems, /* 2 Mouse Systems */ - &mouse_serial_microsoft, /* 3 Microsoft Serial Mouse */ - &mouse_serial_logitech, /* 4 Logitech 3-button Serial Mouse */ - &mouse_serial_mswheel, /* 5 Microsoft Serial Wheel Mouse */ - &mouse_ps2_2_button, /* 6 PS/2 Mouse 2-button */ - &mouse_intellimouse, /* 7 PS/2 Intellimouse 3-button */ - &mouse_amstrad, /* 8 Amstrad PC System Mouse */ - &mouse_olim24, /* 9 Olivetti M24 System Mouse */ - &mouse_inport, /* 10 Microsoft InPort Mouse */ + &mouse_inport, /* 2 Microsoft InPort Mouse */ + &mouse_msystems, /* 3 Mouse Systems */ + &mouse_serial_microsoft, /* 4 Microsoft Serial Mouse */ + &mouse_serial_logitech, /* 5 Logitech 3-button Serial Mouse */ + &mouse_serial_mswheel, /* 6 Microsoft Serial Wheel Mouse */ + &mouse_ps2_2_button, /* 7 PS/2 Mouse 2-button */ + &mouse_intellimouse, /* 8 PS/2 Intellimouse 3-button */ + &mouse_amstrad, /* 9 Amstrad PC System Mouse */ + &mouse_olim24, /* 10 Olivetti M24 System Mouse */ #if 0 &mouse_genius, /* 11 Genius Bus Mouse */ #endif diff --git a/src/mouse.h b/src/mouse.h index daa0cddc3..b79f3492d 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -25,15 +25,15 @@ #define MOUSE_TYPE_GENIUS 11 /* Genius Bus Mouse */ #endif #define MOUSE_TYPE_BUS 1 /* Logitech/ATI Bus Mouse */ -#define MOUSE_TYPE_MSYSTEMS 2 /* Mouse Systems mouse */ -#define MOUSE_TYPE_SERIAL 3 /* Serial Mouse */ -#define MOUSE_TYPE_LOGITECH 4 /* Logitech Serial Mouse */ -#define MOUSE_TYPE_MSWHEEL 5 /* Serial Wheel Mouse */ -#define MOUSE_TYPE_PS2 6 /* IBM PS/2 series Bus Mouse */ -#define MOUSE_TYPE_PS2_MS 7 /* Microsoft Intellimouse PS/2 */ -#define MOUSE_TYPE_AMSTRAD 8 /* Amstrad PC system mouse */ -#define MOUSE_TYPE_OLIM24 9 /* Olivetti M24 system mouse */ -#define MOUSE_TYPE_INPORT 10 /* Microsoft InPort Mouse */ +#define MOUSE_TYPE_INPORT 2 /* Microsoft InPort Mouse */ +#define MOUSE_TYPE_MSYSTEMS 3 /* Mouse Systems mouse */ +#define MOUSE_TYPE_SERIAL 4 /* Serial Mouse */ +#define MOUSE_TYPE_LOGITECH 5 /* Logitech Serial Mouse */ +#define MOUSE_TYPE_MSWHEEL 6 /* Serial Wheel Mouse */ +#define MOUSE_TYPE_PS2 7 /* IBM PS/2 series Bus Mouse */ +#define MOUSE_TYPE_PS2_MS 8 /* Microsoft Intellimouse PS/2 */ +#define MOUSE_TYPE_AMSTRAD 9 /* Amstrad PC system mouse */ +#define MOUSE_TYPE_OLIM24 10 /* Olivetti M24 system mouse */ #define MOUSE_TYPE_MASK 0x0f #define MOUSE_TYPE_3BUTTON (1<<7) /* device has 3+ buttons */ diff --git a/src/mouse_bus.c b/src/mouse_bus.c index 8205c37dc..c090aa3aa 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -32,10 +32,11 @@ * Based on an early driver for MINIX 1.5. * Based on the 86Box PS/2 mouse driver as a framework. * - * Version: @(#)mouse_bus.c 1.0.5 2017/06/02 + * Version: @(#)mouse_bus.c 1.0.6 2017/07/24 * * Author: Fred N. van Kempen, - * Copyright 1989-2017 Fred N. van Kempen. + * TheCollector1995, + * Copyright 1989-2017 Fred N. van Kempen, TheCollector1995. */ #include #include From 9aa0bd3a9992d85ed333cd3575140e2e413f61d3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Jul 2017 18:51:32 +0200 Subject: [PATCH 27/82] Committed the two codegen files I forgot to commit in the previous commit. --- src/CPU/codegen_timing_common.c | 678 ++++++++++++++++++++++++++++++++ src/CPU/codegen_timing_common.h | 226 +++++++++++ 2 files changed, 904 insertions(+) create mode 100644 src/CPU/codegen_timing_common.c create mode 100644 src/CPU/codegen_timing_common.h diff --git a/src/CPU/codegen_timing_common.c b/src/CPU/codegen_timing_common.c new file mode 100644 index 000000000..d32247f35 --- /dev/null +++ b/src/CPU/codegen_timing_common.c @@ -0,0 +1,678 @@ +#include "../ibm.h" +#include "codegen_timing_common.h" + +uint64_t opcode_deps[256] = +{ +/* ADD ADD ADD ADD*/ +/*00*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* ADD ADD PUSH ES POP ES*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP, +/* OR OR OR OR*/ + SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* OR OR PUSH CS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, 0, + +/* ADC ADC ADC ADC*/ +/*10*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* ADC ADC PUSH SS POP SS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP, +/* SBB SBB SBB SBB*/ + SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* SBB SBB PUSH DS POP DS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP, + +/* AND AND AND AND*/ +/*20*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* AND AND DAA*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX, +/* SUB SUB SUB SUB*/ + SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* SUB SUB DAS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX, + +/* XOR XOR XOR XOR*/ +/*30*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* XOR XOR AAA*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX, +/* CMP CMP CMP CMP*/ + SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, +/* CMP CMP AAS*/ + SRCDEP_EAX, SRCDEP_EAX, 0, SRCDEP_EAX | DSTDEP_EAX, + +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX, +/* INC ESP INC EBP INC ESI INC EDI*/ + SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI, + +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ SRCDEP_EAX | IMPL_ESP, SRCDEP_ECX | IMPL_ESP, SRCDEP_EDX | IMPL_ESP, SRCDEP_EBX | IMPL_ESP, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + SRCDEP_ESP | IMPL_ESP, SRCDEP_EBP | IMPL_ESP, SRCDEP_ESI | IMPL_ESP, SRCDEP_EDI | IMPL_ESP, +/* POP EAX POP ECX POP EDX POP EBX*/ + DSTDEP_EAX | IMPL_ESP, DSTDEP_ECX | IMPL_ESP, DSTDEP_EDX | IMPL_ESP, DSTDEP_EBX | IMPL_ESP, +/* POP ESP POP EBP POP ESI POP EDI*/ + DSTDEP_ESP | IMPL_ESP, DSTDEP_EBP | IMPL_ESP, DSTDEP_ESI | IMPL_ESP, DSTDEP_EDI | IMPL_ESP, + +/* PUSHA POPA BOUND ARPL*/ +/*60*/ IMPL_ESP, IMPL_ESP, 0, 0, + 0, 0, 0, 0, +/* PUSH imm IMUL PUSH imm IMUL*/ + IMPL_ESP, DSTDEP_REG | MODRM, IMPL_ESP, DSTDEP_REG | MODRM, +/* INSB INSW OUTSB OUTSW*/ + 0, 0, 0, 0, + +/* Jxx*/ +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/*80*/ 0, 0, 0, 0, +/* TEST TEST XCHG XCHG*/ + SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, +/* MOV MOV MOV MOV*/ + SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, +/* MOV from seg LEA MOV to seg POP*/ + MODRM, DSTDEP_REG | MODRM, MODRM, IMPL_ESP | MODRM, + +/* NOP XCHG XCHG XCHG*/ +/*90*/ 0, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBX | DSTDEP_EBX, +/* XCHG XCHG XCHG XCHG*/ + SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBP | DSTDEP_EBP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDI | DSTDEP_EDI, +/* CBW CWD CALL far WAIT*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EDX, 0, 0, +/* PUSHF POPF SAHF LAHF*/ + IMPL_ESP, IMPL_ESP, SRCDEP_EAX, DSTDEP_EAX, + +/* MOV MOV MOV MOV*/ +/*a0*/ DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX, +/* MOVSB MOVSW CMPSB CMPSW*/ + 0, 0, 0, 0, +/* TEST TEST STOSB STOSW*/ + SRCDEP_EAX, SRCDEP_EAX, 0, 0, +/* LODSB LODSW SCASB SCASW*/ + 0, 0, 0, 0, + +/* MOV*/ +/*b0*/ DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX, + DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX, + DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX, + DSTDEP_ESP, DSTDEP_EBP, DSTDEP_ESI, DSTDEP_EDI, + +/* RET imm RET*/ +/*c0*/ 0, 0, SRCDEP_ESP | DSTDEP_ESP, IMPL_ESP, +/* LES LDS MOV MOV*/ + DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, MODRM, MODRM, +/* ENTER LEAVE RETF RETF*/ + IMPL_ESP, IMPL_ESP, IMPL_ESP, IMPL_ESP, +/* INT3 INT INTO IRET*/ + 0, 0, 0, 0, + + +/*d0*/ 0, 0, 0, 0, +/* AAM AAD SETALC XLAT*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX | SRCDEP_EBX, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/* LOOPNE LOOPE LOOP JCXZ*/ +/*e0*/ SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX, +/* IN AL IN AX OUT_AL OUT_AX*/ + DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX, +/* CALL JMP JMP JMP*/ + IMPL_ESP, 0, 0, 0, +/* IN AL IN AX OUT_AL OUT_AX*/ + SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | SRCDEP_EAX, SRCDEP_EDX | SRCDEP_EAX, + +/* REPNE REPE*/ +/*f0*/ 0, 0, 0, 0, +/* HLT CMC*/ + 0, 0, 0, 0, +/* CLC STC CLI STI*/ + 0, 0, 0, 0, +/* CLD STD INCDEC*/ + 0, 0, MODRM, 0 +}; + +uint64_t opcode_deps_mod3[256] = +{ +/* ADD ADD ADD ADD*/ +/*00*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, +/* ADD ADD PUSH ES POP ES*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP, +/* OR OR OR OR*/ + SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, +/* OR OR PUSH CS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, 0, + +/* ADC ADC ADC ADC*/ +/*10*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, +/* ADC ADC PUSH SS POP SS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP, +/* SBB SBB SBB SBB*/ + SRCDEP_REG |SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, +/* SBB SBB PUSH DS POP DS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP, + +/* AND AND AND AND*/ +/*20*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, +/* AND AND DAA*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX, +/* SUB SUB SUB SUB*/ + SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, +/* SUB SUB DAS*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX, + +/* XOR XOR XOR XOR*/ +/*30*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, +/* XOR XOR AAA*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX, +/* CMP CMP CMP CMP*/ + SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, +/* CMP CMP AAS*/ + SRCDEP_EAX, SRCDEP_EAX, 0, SRCDEP_EAX | DSTDEP_EAX, + +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX, +/* INC ESP INC EBP INC ESI INC EDI*/ + SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI, + +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ SRCDEP_EAX | IMPL_ESP, SRCDEP_ECX | IMPL_ESP, SRCDEP_EDX | IMPL_ESP, SRCDEP_EBX | IMPL_ESP, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + SRCDEP_ESP | IMPL_ESP, SRCDEP_EBP | IMPL_ESP, SRCDEP_ESI | IMPL_ESP, SRCDEP_EDI | IMPL_ESP, +/* POP EAX POP ECX POP EDX POP EBX*/ + DSTDEP_EAX | IMPL_ESP, DSTDEP_ECX | IMPL_ESP, DSTDEP_EDX | IMPL_ESP, DSTDEP_EBX | IMPL_ESP, +/* POP ESP POP EBP POP ESI POP EDI*/ + DSTDEP_ESP | IMPL_ESP, DSTDEP_EBP | IMPL_ESP, DSTDEP_ESI | IMPL_ESP, DSTDEP_EDI | IMPL_ESP, + +/* PUSHA POPA BOUND ARPL*/ +/*60*/ IMPL_ESP, IMPL_ESP, 0, 0, + 0, 0, 0, 0, +/* PUSH imm IMUL PUSH imm IMUL*/ + IMPL_ESP, DSTDEP_REG | SRCDEP_RM | MODRM, IMPL_ESP, DSTDEP_REG | SRCDEP_RM | MODRM, +/* INSB INSW OUTSB OUTSW*/ + 0, 0, 0, 0, + +/* Jxx*/ +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/*80*/ 0, 0, 0, 0, +/* TEST TEST XCHG XCHG*/ + SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, +/* MOV MOV MOV MOV*/ + SRCDEP_REG | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_REG | MODRM, SRCDEP_RM | DSTDEP_REG | MODRM, +/* MOV from seg LEA MOV to seg POP*/ + DSTDEP_RM | MODRM, DSTDEP_REG | MODRM, SRCDEP_RM | MODRM, IMPL_ESP | DSTDEP_RM | MODRM, + +/* NOP XCHG XCHG XCHG*/ +/*90*/ 0, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBX | DSTDEP_EBX, +/* XCHG XCHG XCHG XCHG*/ + SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBP | DSTDEP_EBP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDI | DSTDEP_EDI, +/* CBW CWD CALL far WAIT*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EDX, 0, 0, +/* PUSHF POPF SAHF LAHF*/ + IMPL_ESP, IMPL_ESP, SRCDEP_EAX, DSTDEP_EAX, + +/* MOV MOV MOV MOV*/ +/*a0*/ DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX, +/* MOVSB MOVSW CMPSB CMPSW*/ + 0, 0, 0, 0, +/* TEST TEST STOSB STOSW*/ + SRCDEP_EAX, SRCDEP_EAX, 0, 0, +/* LODSB LODSW SCASB SCASW*/ + 0, 0, 0, 0, + +/* MOV*/ +/*b0*/ DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX, + DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX, + DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX, + DSTDEP_ESP, DSTDEP_EBP, DSTDEP_ESI, DSTDEP_EDI, + +/* RET imm RET*/ +/*c0*/ 0, 0, SRCDEP_ESP | DSTDEP_ESP, IMPL_ESP, +/* LES LDS MOV MOV*/ + DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, DSTDEP_RM | MODRM, DSTDEP_RM | MODRM, +/* ENTER LEAVE RETF RETF*/ + IMPL_ESP, IMPL_ESP, IMPL_ESP, IMPL_ESP, +/* INT3 INT INTO IRET*/ + 0, 0, 0, 0, + + +/*d0*/ 0, 0, 0, 0, +/* AAM AAD SETALC XLAT*/ + SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX | SRCDEP_EBX, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/* LOOPNE LOOPE LOOP JCXZ*/ +/*e0*/ SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX, +/* IN AL IN AX OUT_AL OUT_AX*/ + DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX, +/* CALL JMP JMP JMP*/ + IMPL_ESP, 0, 0, 0, +/* IN AL IN AX OUT_AL OUT_AX*/ + SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | SRCDEP_EAX, SRCDEP_EDX | SRCDEP_EAX, + +/* REPNE REPE*/ +/*f0*/ 0, 0, 0, 0, +/* HLT CMC*/ + 0, 0, 0, 0, +/* CLC STC CLI STI*/ + 0, 0, 0, 0, +/* CLD STD INCDEC*/ + 0, 0, SRCDEP_RM | DSTDEP_RM | MODRM, 0 +}; + +uint64_t opcode_deps_0f[256] = +{ +/*00*/ MODRM, MODRM, MODRM, MODRM, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*10*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*20*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*30*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*40*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*50*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*60*/ MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + MODRM, MODRM, MODRM, MODRM, + MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + 0, 0, MODRM, MODRM, + +/*70*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + MODRM, MODRM, MODRM, 0, + 0, 0, 0, 0, + 0, 0, MODRM, MODRM, + +/*80*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*90*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + +/*a0*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, 0, 0, + MODRM, MODRM, 0, MODRM, + MODRM, MODRM, 0, MODRM, + +/*b0*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + 0, 0, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + +/*c0*/ MODRM, MODRM, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*d0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + 0, MODRM | MMX_MULTIPLY, 0, 0, + MODRM, MODRM, 0, MODRM, + MODRM, MODRM, 0, MODRM, + +/*e0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, + 0, MODRM | MMX_MULTIPLY, 0, 0, + MODRM, MODRM, 0, MODRM, + MODRM, MODRM, 0, MODRM, + +/*f0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + 0, MODRM | MMX_MULTIPLY, 0, 0, + MODRM, MODRM, MODRM, 0, + MODRM, MODRM, MODRM, 0, +}; +uint64_t opcode_deps_0f_mod3[256] = +{ +/*00*/ MODRM, MODRM, MODRM, MODRM, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*10*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*20*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*30*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*40*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*50*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*60*/ MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + MODRM, MODRM, MODRM, MODRM, + MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + 0, 0, MODRM, MODRM, + +/*70*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + MODRM, MODRM, MODRM, 0, + 0, 0, 0, 0, + 0, 0, MODRM, MODRM, + +/*80*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*90*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + +/*a0*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, 0, 0, + MODRM, MODRM, 0, MODRM, + MODRM, MODRM, 0, MODRM, + +/*b0*/ MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + 0, 0, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, + +/*c0*/ MODRM, MODRM, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*d0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + 0, MODRM | MMX_MULTIPLY, 0, 0, + MODRM, MODRM, 0, MODRM, + MODRM, MODRM, 0, MODRM, + +/*e0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, + 0, MODRM | MMX_MULTIPLY, 0, 0, + MODRM, MODRM, 0, MODRM, + MODRM, MODRM, 0, MODRM, + +/*f0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, + 0, MODRM | MMX_MULTIPLY, 0, 0, + MODRM, MODRM, MODRM, 0, + MODRM, MODRM, MODRM, 0, +}; + +uint64_t opcode_deps_shift[8] = +{ + MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM, +}; +uint64_t opcode_deps_shift_mod3[8] = +{ + SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, + SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, +}; + +uint64_t opcode_deps_shift_cl[8] = +{ + MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, + MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, +}; +uint64_t opcode_deps_shift_cl_mod3[8] = +{ + SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, + SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, +}; + +uint64_t opcode_deps_f6[8] = +{ +/* TST NOT NEG*/ + MODRM, 0, MODRM, MODRM, +/* MUL IMUL DIV IDIV*/ + SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM +}; +uint64_t opcode_deps_f6_mod3[8] = +{ +/* TST NOT NEG*/ + SRCDEP_RM | MODRM, 0, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, +/* MUL IMUL DIV IDIV*/ + SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM +}; +uint64_t opcode_deps_f7[8] = +{ +/* TST NOT NEG*/ + MODRM, 0, MODRM, MODRM, +/* MUL IMUL DIV IDIV*/ + SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM +}; +uint64_t opcode_deps_f7_mod3[8] = +{ +/* TST NOT NEG*/ + SRCDEP_RM | MODRM, 0, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, +/* MUL IMUL DIV IDIV*/ + SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM +}; +uint64_t opcode_deps_ff[8] = +{ +/* INC DEC CALL CALL far*/ + MODRM, MODRM, MODRM | IMPL_ESP, MODRM, +/* JMP JMP far PUSH*/ + MODRM, MODRM, MODRM | IMPL_ESP, 0 +}; +uint64_t opcode_deps_ff_mod3[8] = +{ +/* INC DEC CALL CALL far*/ + SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM | IMPL_ESP, MODRM, +/* JMP JMP far PUSH*/ + SRCDEP_RM | MODRM, MODRM, SRCDEP_RM | MODRM | IMPL_ESP, 0 +}; + +uint64_t opcode_deps_d8[8] = +{ +/* FADDs FMULs FCOMs FCOMPs*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_POP | FPU_READ_ST0 | MODRM, +/* FSUBs FSUBRs FDIVs FDIVRs*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM +}; +uint64_t opcode_deps_d8_mod3[8] = +{ +/* FADD FMUL FCOM FCOMP*/ + FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_READ_ST0 | FPU_READ_STREG, FPU_POP | FPU_READ_ST0 | FPU_READ_STREG, +/* FSUB FSUBR FDIV FDIVR*/ + FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG +}; + +uint64_t opcode_deps_d9[8] = +{ +/* FLDs FSTs FSTPs*/ + FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_POP | MODRM, +/* FLDENV FLDCW FSTENV FSTCW*/ + MODRM, MODRM, MODRM, MODRM +}; +uint64_t opcode_deps_d9_mod3[64] = +{ + /*FLD*/ + FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, + FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, + /*FXCH*/ + FPU_FXCH, FPU_FXCH, FPU_FXCH, FPU_FXCH, + FPU_FXCH, FPU_FXCH, FPU_FXCH, FPU_FXCH, + /*FNOP*/ + 0, 0, 0, 0, 0, 0, 0, 0, + /*FSTP*/ + FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, + FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, +/* opFCHS opFABS*/ + 0, 0, 0, 0, +/* opFTST opFXAM*/ + 0, 0, 0, 0, +/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/ + FPU_PUSH, FPU_PUSH, FPU_PUSH, FPU_PUSH, +/* opFLDEG2 opFLDLN2 opFLDZ*/ + FPU_PUSH, FPU_PUSH, FPU_PUSH, 0, +/* opF2XM1 opFYL2X opFPTAN opFPATAN*/ + 0, 0, 0, 0, +/* opFDECSTP opFINCSTP,*/ + 0, 0, 0, 0, +/* opFPREM opFSQRT opFSINCOS*/ + 0, 0, 0, 0, +/* opFRNDINT opFSCALE opFSIN opFCOS*/ + 0, 0, 0, 0 +}; + +uint64_t opcode_deps_da[8] = +{ +/* FIADDl FIMULl FICOMl FICOMPl*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, +/* FISUBl FISUBRl FIDIVl FIDIVRl*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM +}; +uint64_t opcode_deps_da_mod3[8] = +{ + 0, 0, 0, 0, +/* FCOMPP*/ + 0, FPU_POP2, 0, 0 +}; + + +uint64_t opcode_deps_db[8] = +{ +/* FLDil FSTil FSTPil*/ + FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, +/* FLDe FSTPe*/ + 0, FPU_PUSH | MODRM, 0, FPU_READ_ST0 | FPU_POP | MODRM +}; +uint64_t opcode_deps_db_mod3[64] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + + + 0, 0, 0, 0, 0, 0, 0, 0, + +/* opFNOP opFCLEX opFINIT*/ + 0, 0, 0, 0, +/* opFNOP opFNOP*/ + 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +uint64_t opcode_deps_dc[8] = +{ +/* FADDd FMULd FCOMd FCOMPd*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, +/* FSUBd FSUBRd FDIVd FDIVRd*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM +}; +uint64_t opcode_deps_dc_mod3[8] = +{ +/* opFADDr opFMULr*/ + FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, 0, 0, +/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ + FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG +}; + +uint64_t opcode_deps_dd[8] = +{ +/* FLDd FSTd FSTPd*/ + FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, +/* FRSTOR FSAVE FSTSW*/ + MODRM, 0, MODRM, MODRM +}; +uint64_t opcode_deps_dd_mod3[8] = +{ +/* FFFREE FST FSTP*/ + 0, 0, FPU_READ_ST0 | FPU_WRITE_STREG, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, +/* FUCOM FUCOMP*/ + FPU_READ_ST0 | FPU_READ_STREG, FPU_READ_ST0 | FPU_READ_STREG | FPU_POP, 0, 0 +}; + +uint64_t opcode_deps_de[8] = +{ +/* FIADDw FIMULw FICOMw FICOMPw*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, +/* FISUBw FISUBRw FIDIVw FIDIVRw*/ + FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM +}; +uint64_t opcode_deps_de_mod3[8] = +{ +/* FADDP FMULP FCOMPP*/ + FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, 0, FPU_READ_ST0 | FPU_READ_ST1 | FPU_POP2, +/* FSUBP FSUBRP FDIVP FDIVRP*/ + FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP +}; + +uint64_t opcode_deps_df[8] = +{ +/* FILDiw FISTiw FISTPiw*/ + FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, +/* FILDiq FBSTP FISTPiq*/ + 0, FPU_PUSH | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, FPU_READ_ST0 | FPU_POP | MODRM +}; +uint64_t opcode_deps_df_mod3[8] = +{ + 0, 0, 0, 0, +/* FSTSW AX*/ + 0, 0, 0, 0 +}; + +uint64_t opcode_deps_81[8] = +{ + MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM +}; +uint64_t opcode_deps_81_mod3[8] = +{ + SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, + SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM +}; +uint64_t opcode_deps_8x[8] = +{ + MODRM, MODRM, MODRM, MODRM, + MODRM, MODRM, MODRM, MODRM +}; +uint64_t opcode_deps_8x_mod3[8] = +{ + SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, + SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM +}; diff --git a/src/CPU/codegen_timing_common.h b/src/CPU/codegen_timing_common.h new file mode 100644 index 000000000..19856ed99 --- /dev/null +++ b/src/CPU/codegen_timing_common.h @@ -0,0 +1,226 @@ +#include "codegen_ops.h" + +/*Instruction has input dependency on register in REG field*/ +#define SRCDEP_REG (1ull << 0) +/*Instruction has input dependency on register in R/M field*/ +#define SRCDEP_RM (1ull << 1) +/*Instruction modifies register in REG field*/ +#define DSTDEP_REG (1ull << 2) +/*Instruction modifies register in R/M field*/ +#define DSTDEP_RM (1ull << 3) + +#define SRCDEP_SHIFT 4 +#define DSTDEP_SHIFT 12 + +/*Instruction has input dependency on given register*/ +#define SRCDEP_EAX (1ull << 4) +#define SRCDEP_ECX (1ull << 5) +#define SRCDEP_EDX (1ull << 6) +#define SRCDEP_EBX (1ull << 7) +#define SRCDEP_ESP (1ull << 8) +#define SRCDEP_EBP (1ull << 9) +#define SRCDEP_ESI (1ull << 10) +#define SRCDEP_EDI (1ull << 11) + +/*Instruction modifies given register*/ +#define DSTDEP_EAX (1ull << 12) +#define DSTDEP_ECX (1ull << 13) +#define DSTDEP_EDX (1ull << 14) +#define DSTDEP_EBX (1ull << 15) +#define DSTDEP_ESP (1ull << 16) +#define DSTDEP_EBP (1ull << 17) +#define DSTDEP_ESI (1ull << 18) +#define DSTDEP_EDI (1ull << 19) + +/*Instruction has ModR/M byte*/ +#define MODRM (1ull << 20) +/*Instruction implicitly uses ESP*/ +#define IMPL_ESP (1ull << 21) + +/*Instruction is MMX shift or pack/unpack instruction*/ +#define MMX_SHIFTPACK (1ull << 22) +/*Instruction is MMX multiply instruction*/ +#define MMX_MULTIPLY (1ull << 23) + +/*Instruction pops the FPU stack*/ +#define FPU_POP (1ull << 24) +/*Instruction pops the FPU stack twice*/ +#define FPU_POP2 (1ull << 25) +/*Instruction pushes onto the FPU stack*/ +#define FPU_PUSH (1ull << 26) + +/*Instruction writes to ST(0)*/ +#define FPU_WRITE_ST0 (1ull << 27) +/*Instruction reads from ST(0)*/ +#define FPU_READ_ST0 (1ull << 28) +/*Instruction reads from and writes to ST(0)*/ +#define FPU_RW_ST0 (3ull << 27) + +/*Instruction reads from ST(1)*/ +#define FPU_READ_ST1 (1ull << 29) +/*Instruction writes to ST(1)*/ +#define FPU_WRITE_ST1 (1ull << 30) +/*Instruction reads from and writes to ST(1)*/ +#define FPU_RW_ST1 (3ull << 29) + +/*Instruction reads from ST(reg)*/ +#define FPU_READ_STREG (1ull << 31) +/*Instruction writes to ST(reg)*/ +#define FPU_WRITE_STREG (1ull << 32) +/*Instruction reads from and writes to ST(reg)*/ +#define FPU_RW_STREG (3ull << 30) + +#define FPU_FXCH (1ull << 33) + + +#define REGMASK_IMPL_ESP (1 << 8) +#define REGMASK_SHIFTPACK (1 << 9) +#define REGMASK_MULTIPLY (1 << 9) + + +extern uint64_t opcode_deps[256]; +extern uint64_t opcode_deps_mod3[256]; +extern uint64_t opcode_deps_0f[256]; +extern uint64_t opcode_deps_0f_mod3[256]; +extern uint64_t opcode_deps_shift[8]; +extern uint64_t opcode_deps_shift_mod3[8]; +extern uint64_t opcode_deps_shift_cl[8]; +extern uint64_t opcode_deps_shift_cl_mod3[8]; +extern uint64_t opcode_deps_f6[8]; +extern uint64_t opcode_deps_f6_mod3[8]; +extern uint64_t opcode_deps_f7[8]; +extern uint64_t opcode_deps_f7_mod3[8]; +extern uint64_t opcode_deps_ff[8]; +extern uint64_t opcode_deps_ff_mod3[8]; +extern uint64_t opcode_deps_d8[8]; +extern uint64_t opcode_deps_d8_mod3[8]; +extern uint64_t opcode_deps_d9[8]; +extern uint64_t opcode_deps_d9_mod3[64]; +extern uint64_t opcode_deps_da[8]; +extern uint64_t opcode_deps_da_mod3[8]; +extern uint64_t opcode_deps_db[8]; +extern uint64_t opcode_deps_db_mod3[64]; +extern uint64_t opcode_deps_dc[8]; +extern uint64_t opcode_deps_dc_mod3[8]; +extern uint64_t opcode_deps_dd[8]; +extern uint64_t opcode_deps_dd_mod3[8]; +extern uint64_t opcode_deps_de[8]; +extern uint64_t opcode_deps_de_mod3[8]; +extern uint64_t opcode_deps_df[8]; +extern uint64_t opcode_deps_df_mod3[8]; +extern uint64_t opcode_deps_81[8]; +extern uint64_t opcode_deps_81_mod3[8]; +extern uint64_t opcode_deps_8x[8]; +extern uint64_t opcode_deps_8x_mod3[8]; + + + +static inline uint32_t get_addr_regmask(uint64_t data, uint32_t fetchdat, int op_32) +{ + uint32_t addr_regmask = 0; + + if (data & MODRM) + { + uint8_t modrm = fetchdat & 0xff; + + if ((modrm & 0xc0) != 0xc0) + { + if (op_32 & 0x200) + { + if ((modrm & 0x7) == 4) + { + uint8_t sib = (fetchdat >> 8) & 0xff; + + if ((modrm & 0xc0) != 0xc0 && (sib & 7) != 5) + { + addr_regmask = 1 << (sib & 7); + if ((sib & 0x38) != 0x20) + addr_regmask |= 1 << ((sib >> 3) & 7); + } + } + else if ((modrm & 0xc7) != 5) + { + addr_regmask = 1 << (modrm & 7); + } + } + else + { + if ((modrm & 0xc7) != 0x06) + { + switch (modrm & 7) + { + case 0: addr_regmask = REG_BX | REG_SI; break; + case 1: addr_regmask = REG_BX | REG_DI; break; + case 2: addr_regmask = REG_BP | REG_SI; break; + case 3: addr_regmask = REG_BP | REG_DI; break; + case 4: addr_regmask = REG_SI; break; + case 5: addr_regmask = REG_DI; break; + case 6: addr_regmask = REG_BP; break; + case 7: addr_regmask = REG_BX; break; + } + } + } + } + } + + if (data & IMPL_ESP) + addr_regmask |= REGMASK_IMPL_ESP; + + return addr_regmask; +} + +static inline uint32_t get_srcdep_mask(uint64_t data, uint32_t fetchdat, int bit8, int op_32) +{ + uint32_t mask = 0; + if (data & SRCDEP_REG) + { + int reg = (fetchdat >> 3) & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + if (data & SRCDEP_RM) + { + int reg = fetchdat & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + mask |= ((data >> SRCDEP_SHIFT) & 0xff); + if (data & MMX_SHIFTPACK) + mask |= REGMASK_SHIFTPACK; + if (data & MMX_MULTIPLY) + mask |= REGMASK_MULTIPLY; + + mask |= get_addr_regmask(data, fetchdat, op_32); + + return mask; +} + +static inline uint32_t get_dstdep_mask(uint64_t data, uint32_t fetchdat, int bit8) +{ + uint32_t mask = 0; + if (data & DSTDEP_REG) + { + int reg = (fetchdat >> 3) & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + if (data & DSTDEP_RM) + { + int reg = fetchdat & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + mask |= ((data >> DSTDEP_SHIFT) & 0xff); + if (data & MMX_SHIFTPACK) + mask |= REGMASK_SHIFTPACK; + if (data & MMX_MULTIPLY) + mask |= REGMASK_MULTIPLY; + if (data & IMPL_ESP) + mask |= REGMASK_IMPL_ESP | (1 << REG_ESP); + + return mask; +} From bac4a8ef9740513bf170cb9d001acdd2bdd16b99 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 24 Jul 2017 20:51:06 +0200 Subject: [PATCH 28/82] Small fix for the InPort mouse, makes it work in every OS now, including IBM OS/2 1.x. --- src/mouse_bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mouse_bus.c b/src/mouse_bus.c index c090aa3aa..a47287c24 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -258,6 +258,7 @@ static uint8_t inport_read(uint16_t port, void *priv) { case INP_CTRL_READ_BUTTONS: r = inport->but; + r |= 0x40; break; case INP_CTRL_READ_X: From 9eb563a1ab346301d71d8bab57ccdcba8c9c3007 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 24 Jul 2017 22:49:51 +0200 Subject: [PATCH 29/82] Fixed VisiCorp Vision's Mouse Systems Mouse's poller. --- src/mouse_serial.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mouse_serial.c b/src/mouse_serial.c index fa7e709c6..8fe228093 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -295,10 +295,8 @@ uint8_t mouse_serial_msystems_poll(int x, int y, int z, int b, void *p) { mouse_serial_t *mouse = (mouse_serial_t *)p; SERIAL *serial = mouse->serial; - uint8_t mousedat[4]; + uint8_t mousedat[5]; - if (!(serial->ier & 1)) - return 0xff; if (!x && !y && b == mouse->oldb) return 0xff; @@ -351,7 +349,7 @@ void mousecallback(void *p) switch(mouse->type) { case 0: - serial_write_fifo(mouse->serial, 'H'); + serial_write_fifo(mouse->serial, 'M'); break; case 1: default: From bb0840fbe046593dbd4b2e94a1b11be952b3ff1a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Jul 2017 00:36:17 +0200 Subject: [PATCH 30/82] Applied the last two mainline PCem commits; Restored the Mouse Systems mouse identify byte back to 'H'. --- src/CPU/386_dynarec_ops.c | 2 - src/CPU/386_ops.h | 267 ++++++++++++++++++-------------------- src/CPU/x86_ops_rep.h | 50 ++----- src/CPU/x86seg.c | 149 +++++++++------------ src/mouse_serial.c | 2 +- 5 files changed, 206 insertions(+), 264 deletions(-) diff --git a/src/CPU/386_dynarec_ops.c b/src/CPU/386_dynarec_ops.c index db6958e5a..e0e018872 100644 --- a/src/CPU/386_dynarec_ops.c +++ b/src/CPU/386_dynarec_ops.c @@ -17,8 +17,6 @@ #include "386_common.h" -extern int trap; - extern uint16_t *mod1add[2][8]; extern uint32_t *mod1seg[8]; diff --git a/src/CPU/386_ops.h b/src/CPU/386_ops.h index 71a6f1e4b..17d27c7fb 100644 --- a/src/CPU/386_ops.h +++ b/src/CPU/386_ops.h @@ -227,17 +227,6 @@ static int op0F_l_a32(uint32_t fetchdat) return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); } -static int opREP_ignore(uint32_t fetchdat) -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 0; - cpu_state.pc++; - - CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_PREFIX(); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} - OpFn OP_TABLE(286_0f)[1024] = { /*16-bit data, 16-bit addr*/ @@ -1427,180 +1416,180 @@ OpFn OP_TABLE(REPE)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_w_a16,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_w_a16,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_w_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPE_w_a16,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_w_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPE_w_a16,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_w_a16,opGS_REPE_w_a16,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPE_w_a16,opGS_REPE_w_a16,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_E,opREP_CMPSW_a16_E,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_E,opREP_SCASW_a16_E, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_E,opREP_CMPSW_a16_E,0, 0, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_E,opREP_SCASW_a16_E, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_l_a16,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_l_a16,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_l_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPE_l_a16,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_l_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPE_l_a16,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_l_a16,opGS_REPE_l_a16,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPE_l_a16,opGS_REPE_l_a16,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_E,opREP_CMPSL_a16_E,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_E,opREP_SCASL_a16_E, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_E,opREP_CMPSL_a16_E,0, 0, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_E,opREP_SCASL_a16_E, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_w_a32,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_w_a32,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_w_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPE_w_a32,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_w_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPE_w_a32,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_w_a32,opGS_REPE_w_a32,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPE_w_a32,opGS_REPE_w_a32,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_E,opREP_CMPSW_a32_E,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_E,opREP_SCASW_a32_E, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_E,opREP_CMPSW_a32_E,0, 0, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_E,opREP_SCASW_a32_E, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPE_l_a32,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPE_l_a32,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_l_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPE_l_a32,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_l_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPE_l_a32,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPE_l_a32,opGS_REPE_l_a32,op_66_REPE, op_67_REPE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPE_l_a32,opGS_REPE_l_a32,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_E,opREP_CMPSL_a32_E,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_E,opREP_SCASL_a32_E, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_E,opREP_CMPSL_a32_E,0, 0, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_E,opREP_SCASL_a32_E, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; OpFn OP_TABLE(REPNE)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_w_a16,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_w_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_w_a16,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_w_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_w_a16,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_w_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_w_a16,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_w_a16,opGS_REPNE_w_a16,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPNE_w_a16,opGS_REPNE_w_a16,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_NE,opREP_CMPSW_a16_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_NE,opREP_SCASW_a16_NE, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_NE,opREP_CMPSW_a16_NE,0, 0, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_NE,opREP_SCASW_a16_NE, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_l_a16,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_l_a16,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_l_a16,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_l_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_l_a16,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_l_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_l_a16,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_l_a16,opGS_REPNE_l_a16,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPNE_l_a16,opGS_REPNE_l_a16,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_NE,opREP_CMPSL_a16_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_NE,opREP_SCASL_a16_NE, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_NE,opREP_CMPSL_a16_NE,0, 0, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_NE,opREP_SCASL_a16_NE, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_w_a32,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_w_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_w_a32,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_w_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_w_a32,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_w_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_w_a32,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_w_a32,opGS_REPNE_w_a32,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPNE_w_a32,opGS_REPNE_w_a32,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_NE,opREP_CMPSW_a32_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_NE,opREP_SCASW_a32_NE, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_NE,opREP_CMPSW_a32_NE,0, 0, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_NE,opREP_SCASW_a32_NE, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*10*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*20*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opES_REPNE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opCS_REPNE_l_a32,opREP_ignore, -/*30*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opSS_REPNE_l_a32,opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opDS_REPNE_l_a32,opREP_ignore, +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_l_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_l_a32,0, +/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_l_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_l_a32,0, -/*40*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*50*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*60*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opFS_REPNE_l_a32,opGS_REPNE_l_a32,op_66_REPNE, op_67_REPNE, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, -/*70*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, opFS_REPNE_l_a32,opGS_REPNE_l_a32,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*80*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*90*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*a0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_NE,opREP_CMPSL_a32_NE,opREP_ignore, opREP_ignore, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_NE,opREP_SCASL_a32_NE, -/*b0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_NE,opREP_CMPSL_a32_NE,0, 0, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_NE,opREP_SCASL_a32_NE, +/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*c0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*d0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*e0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, -/*f0*/ opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, opREP_ignore, +/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; diff --git a/src/CPU/x86_ops_rep.h b/src/CPU/x86_ops_rep.h index b26b3be3d..065695706 100644 --- a/src/CPU/x86_ops_rep.h +++ b/src/CPU/x86_ops_rep.h @@ -1,3 +1,5 @@ +extern int trap; + #define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ static int opREP_INSB_ ## size(uint32_t fetchdat) \ { \ @@ -166,10 +168,8 @@ static int opREP_MOVSB_ ## size(uint32_t fetchdat) { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ uint8_t temp; \ @@ -201,10 +201,8 @@ static int opREP_MOVSW_ ## size(uint32_t fetchdat) { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ uint16_t temp; \ @@ -236,10 +234,8 @@ static int opREP_MOVSL_ ## size(uint32_t fetchdat) { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ uint32_t temp; \ @@ -273,10 +269,8 @@ static int opREP_STOSB_ ## size(uint32_t fetchdat) { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ @@ -303,10 +297,8 @@ static int opREP_STOSW_ ## size(uint32_t fetchdat) { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+1); \ @@ -333,10 +325,8 @@ static int opREP_STOSL_ ## size(uint32_t fetchdat) { \ int writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+3); \ @@ -364,10 +354,8 @@ static int opREP_LODSB_ ## size(uint32_t fetchdat) { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -393,10 +381,8 @@ static int opREP_LODSW_ ## size(uint32_t fetchdat) { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -422,10 +408,8 @@ static int opREP_LODSL_ ## size(uint32_t fetchdat) { \ int reads = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ while (CNT_REG > 0) \ { \ EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -536,10 +520,8 @@ static int opREP_SCASB_ ## size(uint32_t fetchdat) { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ @@ -569,10 +551,8 @@ static int opREP_SCASW_ ## size(uint32_t fetchdat) { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ @@ -602,10 +582,8 @@ static int opREP_SCASL_ ## size(uint32_t fetchdat) { \ int reads = 0, total_cycles = 0, tempz; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - \ if (trap) \ - cycles_end = cycles+1; \ - \ + cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ diff --git a/src/CPU/x86seg.c b/src/CPU/x86seg.c index 9fa8cf8f9..177a555ca 100644 --- a/src/CPU/x86seg.c +++ b/src/CPU/x86seg.c @@ -2133,7 +2133,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) base=segdat[1]|((segdat[2]&0xFF)<<16); limit=segdat[0]; - if(is386) { base |= (segdat[3]>>8)<<24; @@ -2144,7 +2143,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) { if (limit < 103) { - pclog("32-bit TSS %04X limit less than 103.\n", seg); x86ts(NULL, seg); return; } @@ -2161,7 +2159,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) if (cpu_state.abrt) return; if (optype==IRET) flags&=~NT_FLAG; - + cpu_386_flags_rebuild(); writememl(tr.base,0x1C,cr3); writememl(tr.base,0x20,cpu_state.pc); @@ -2200,14 +2198,14 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) if (cpu_state.abrt) return; } + new_cr3=readmeml(base,0x1C); new_pc=readmeml(base,0x20); new_flags=readmeml(base,0x24); - if (optype == OPTYPE_INT || optype == CALL) new_flags |= NT_FLAG; - + new_eax=readmeml(base,0x28); new_ecx=readmeml(base,0x2C); new_edx=readmeml(base,0x30); @@ -2245,70 +2243,72 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) } ldt.base=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24); - if (eflags&VM_FLAG) + if (eflags & VM_FLAG) { - x86gpf(NULL,0); - return; - } - - if (!(new_cs&~3)) - { - x86ts(NULL,0); - return; - } - addr=new_cs&~7; - if (new_cs&4) - { - if (addr>=ldt.limit) - { - x86ts(NULL,new_cs&~3); - return; - } - addr+=ldt.base; + loadcs(new_cs); + set_use32(0); } else { - if (addr>=gdt.limit) + if (!(new_cs&~3)) { + x86ts(NULL,0); + return; + } + addr=new_cs&~7; + if (new_cs&4) + { + if (addr>=ldt.limit) + { + x86ts(NULL,new_cs&~3); + return; + } + addr+=ldt.base; + } + else + { + if (addr>=gdt.limit) + { + x86ts(NULL,new_cs&~3); + return; + } + addr+=gdt.base; + } + segdat2[0]=readmemw(0,addr); + segdat2[1]=readmemw(0,addr+2); + segdat2[2]=readmemw(0,addr+4); + segdat2[3]=readmemw(0,addr+6); + if (!(segdat2[2]&0x8000)) + { + x86np("TS loading CS not present\n", new_cs & 0xfffc); + return; + } + switch (segdat2[2]&0x1F00) + { + case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming*/ + if ((new_cs&3) != DPL2) + { + x86ts(NULL,new_cs&~3); + return; + } + break; + case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ + if ((new_cs&3) < DPL2) + { + x86ts(NULL,new_cs&~3); + return; + } + break; + default: x86ts(NULL,new_cs&~3); return; } - addr+=gdt.base; - } - segdat2[0]=readmemw(0,addr); - segdat2[1]=readmemw(0,addr+2); - segdat2[2]=readmemw(0,addr+4); - segdat2[3]=readmemw(0,addr+6); - if (!(segdat2[2]&0x8000)) - { - x86np("TS loading CS not present\n", new_cs & 0xfffc); - return; - } - switch (segdat2[2]&0x1F00) - { - case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming*/ - if ((new_cs&3) != DPL2) - { - x86ts(NULL,new_cs&~3); - return; - } - break; - case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ - if ((new_cs&3) < DPL2) - { - x86ts(NULL,new_cs&~3); - return; - } - break; - default: - x86ts(NULL,new_cs&~3); - return; - } - CS=new_cs; - do_seg_load(&_cs, segdat2); - if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); - set_use32(segdat2[3] & 0x40); + CS=new_cs; + do_seg_load(&_cs, segdat2); + if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + set_use32(segdat2[3] & 0x40); + } EAX=new_eax; ECX=new_ecx; @@ -2319,28 +2319,20 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) ESI=new_esi; EDI=new_edi; - if (output) pclog("Load ES %04X\n",new_es); loadseg(new_es,&_es); - if (output) pclog("Load SS %04X\n",new_ss); loadseg(new_ss,&_ss); - if (output) pclog("Load DS %04X\n",new_ds); loadseg(new_ds,&_ds); - if (output) pclog("Load FS %04X\n",new_fs); loadseg(new_fs,&_fs); - if (output) pclog("Load GS %04X\n",new_gs); loadseg(new_gs,&_gs); - - if (output) pclog("Resuming at %04X:%08X\n",CS,cpu_state.pc); } else { if (limit < 43) { - pclog("16-bit TSS %04X limit less than 43.\n", seg); x86ts(NULL, seg); return; } - + if (optype==JMP || optype==CALL || optype==OPTYPE_INT) { if (tr.seg&4) tempw=readmemw(ldt.base,(seg&~7)+4); @@ -2353,7 +2345,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) if (cpu_state.abrt) return; if (optype==IRET) flags&=~NT_FLAG; - + cpu_386_flags_rebuild(); writememw(tr.base,0x0E,cpu_state.pc); writememw(tr.base,0x10,flags); @@ -2392,15 +2384,13 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) new_pc=readmemw(base,0x0E); new_flags=readmemw(base,0x10); - if (optype == OPTYPE_INT || optype == CALL) new_flags |= NT_FLAG; - + new_eax=readmemw(base,0x12); new_ecx=readmemw(base,0x14); new_edx=readmemw(base,0x16); new_ebx=readmemw(base,0x18); - new_esp=readmemw(base,0x1A); new_ebp=readmemw(base,0x1C); new_esi=readmemw(base,0x1E); @@ -2434,7 +2424,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) if (!(new_cs&~3)) { - pclog("TS loading null CS\n"); x86ts(NULL,0); return; } @@ -2443,7 +2432,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) { if (addr>=ldt.limit) { - pclog("Bigger than LDT limit %04X %04X %04X TS\n",new_cs,ldt.limit,addr); x86ts(NULL,new_cs&~3); return; } @@ -2453,7 +2441,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) { if (addr>=gdt.limit) { - pclog("Bigger than GDT limit %04X %04X TS\n",new_cs,gdt.limit); x86ts(NULL,new_cs&~3); return; } @@ -2465,7 +2452,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) segdat2[3]=readmemw(0,addr+6); if (!(segdat2[2]&0x8000)) { - pclog("TS loading CS not present\n"); x86np("TS loading CS not present\n", new_cs & 0xfffc); return; } @@ -2474,7 +2460,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming*/ if ((new_cs&3) != DPL2) { - pclog("TS load CS non-conforming RPL != DPL"); x86ts(NULL,new_cs&~3); return; } @@ -2482,13 +2467,11 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ if ((new_cs&3) < DPL2) { - pclog("TS load CS non-conforming RPL < DPL"); x86ts(NULL,new_cs&~3); return; } break; default: - pclog("TS load CS not code segment\n"); x86ts(NULL,new_cs&~3); return; } @@ -2507,19 +2490,14 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) ESI=new_esi | 0xFFFF0000; EDI=new_edi | 0xFFFF0000; - if (output) pclog("Load ES %04X\n",new_es); loadseg(new_es,&_es); - if (output) pclog("Load SS %04X\n",new_ss); loadseg(new_ss,&_ss); - if (output) pclog("Load DS %04X\n",new_ds); loadseg(new_ds,&_ds); if (is386) { loadseg(0,&_fs); loadseg(0,&_gs); } - - if (output) pclog("Resuming at %04X:%08X\n",CS,cpu_state.pc); } tr.seg=seg; @@ -2527,4 +2505,3 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) tr.limit=limit; tr.access=segdat[2]>>8; } - diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 8fe228093..bbad6b0d8 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -349,7 +349,7 @@ void mousecallback(void *p) switch(mouse->type) { case 0: - serial_write_fifo(mouse->serial, 'M'); + serial_write_fifo(mouse->serial, 'H'); break; case 1: default: From e3952f0618e01846ef016ae1a1b035dc2ee431cc Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 25 Jul 2017 20:15:31 +0200 Subject: [PATCH 31/82] Fixed the Bus Mouse IRQ firing when needed. --- src/mouse_bus.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/mouse_bus.c b/src/mouse_bus.c index a47287c24..5d20f2f31 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -389,11 +389,7 @@ static uint8_t busmouse_poll(int x, int y, int z, int b, void *priv) busmouse->mouse_buttons_last = busmouse->mouse_buttons; } - /* if interrupts are on, fire the interrupt */ - if (busmouse->interrupts) - { - picint(1 << busmouse->irq); - } + picint(1 << busmouse->irq); return(0); } From 15d90054f1bcaf86df24e20966ec440013c2df39 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Jul 2017 20:32:48 +0200 Subject: [PATCH 32/82] Configuration entry and section deletion are now by actually deleting the item from the linked list, properly fixes the floppy/hard disk corruption bug. --- src/config.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/config.c b/src/config.c index d7e62004f..6bc9bf1f6 100644 --- a/src/config.c +++ b/src/config.c @@ -81,6 +81,21 @@ typedef struct entry_t (new)->next = NULL; \ } +#define list_delete(old, head) \ + { \ + struct list_t *cur = head; \ + struct list_t *next = head; \ + \ + while (next->next != old) \ + { \ + cur = next; \ + next = next->next; \ + } \ + \ + cur->next = next->next; \ + free(next); \ + } + void config_dump(void) { @@ -471,8 +486,7 @@ void config_delete_var(char *head, char *name) if (!entry) return; - /* memset(entry->name, 0, strlen(entry->name)); */ - entry->name[0] = 0; + list_delete(&entry->list, §ion->entry_head); return; } @@ -489,8 +503,7 @@ void config_delete_section_if_empty(char *head) if (entries_num(section) == 0) { - /* memset(section->name, 0, strlen(section->name)); */ - section->name[0] = 0; + list_delete(§ion->list, &config_head); } return; From 02f5d663d0c752f706ce318ff2021df1253d0751 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 26 Jul 2017 00:16:54 +0200 Subject: [PATCH 33/82] New turbo floppy poller, should be a bit faster than before. --- src/disc.c | 12 +- src/disc.h | 5 + src/disc_86f.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++++- src/disc_86f.h | 6 + src/disc_fdi.c | 2 + src/disc_imd.c | 25 +++++ src/disc_img.c | 15 +++ src/disc_td0.c | 20 ++++ src/fdd.c | 5 + src/fdd.h | 2 + 10 files changed, 382 insertions(+), 8 deletions(-) diff --git a/src/disc.c b/src/disc.c index 1a0321f39..bc6a7977e 100644 --- a/src/disc.c +++ b/src/disc.c @@ -194,11 +194,6 @@ double disc_byteperiod(int drive) if (drives[drive].byteperiod) { - if (fdd_get_turbo(drive)) - { - return 1.0; - } - return drives[drive].byteperiod(drive); } else @@ -217,7 +212,12 @@ double disc_real_period(int drive) dusec = (double) TIMER_USEC; /* This is a giant hack but until the timings become even more correct, this is needed to make floppies work right on that BIOS. */ - if ((romset == ROM_MRTHOR) && !fdd_get_turbo(drive)) + if (fdd_get_turbo(drive)) + { + return (32.0 * dusec); + } + + if (romset == ROM_MRTHOR) { return (ddbp * dusec) / 4.0; } diff --git a/src/disc.h b/src/disc.h index eb5c7a1bd..b6f5f7c43 100644 --- a/src/disc.h +++ b/src/disc.h @@ -231,5 +231,10 @@ typedef union sector_id_fields_t id; } sector_id_t; +void d86f_set_version(int drive, uint16_t version); + +void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); +void d86f_zero_bit_field(int drive, int side); + #endif /*EMU_DISC_H*/ diff --git a/src/disc_86f.c b/src/disc_86f.c index 9eb713365..eac0b9128 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -35,8 +35,6 @@ #include "fdd.h" #include "ibm.h" -#define D86FVER 0x020B - #define CHUNK 16384 uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ @@ -252,6 +250,8 @@ struct __attribute__((__packed__)) uint8_t *filebuf; uint8_t *outbuf; uint32_t dma_over; + int turbo_pos; + uint16_t sector_id_bit_field[2][256][256][256]; } d86f[FDD_NUM]; #ifdef __MSC__ # pragma pack(pop) @@ -273,6 +273,28 @@ void d86f_log(const char *format, ...) #endif } +void d86f_zero_bit_field(int drive, int side) +{ + int i = 0; + int j = 0; + int k = 0; + int l = 0; + + for (i = 0; i < side; i++) + { + for (j = 0; j < 256; j++) + { + for (k = 0; k < 256; k++) + { + for (l = 0; l < 256; l++) + { + d86f[drive].sector_id_bit_field[i][j][k][l] = 0; + } + } + } + } +} + static void d86f_setupcrc(uint16_t poly) { int c = 256, bc; @@ -490,6 +512,11 @@ uint32_t common_get_raw_size(int drive, int side) return ((((uint32_t) size) >> 4) << 4) + d86f_handler[drive].extra_bit_cells(drive, side); } +void d86f_set_version(int drive, uint16_t version) +{ + d86f[drive].version = version; +} + void d86f_unregister(int drive) { d86f_handler[drive].disk_flags = null_disk_flags; @@ -1793,6 +1820,20 @@ void d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_ fdc_sector_finishread(); } +void d86f_format_turbo_finish(int drive, int side, int do_write) +{ + d86f[drive].state = STATE_IDLE; + + if (do_write) + { + d86f_handler[drive].writeback(drive); + } + + d86f[drive].error_condition = 0; + d86f[drive].datac = 0; + fdc_sector_finishread(); +} + void d86f_format_track(int drive, int side, int do_write) { int data; @@ -2001,6 +2042,251 @@ void d86f_format_track_nop(int drive, int side) d86f_format_track(drive, side, 0); } +void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n) +{ + d86f[drive].last_sector.id.c = c; + d86f[drive].last_sector.id.h = h; + d86f[drive].last_sector.id.r = r; + d86f[drive].last_sector.id.n = n; +} + +void d86f_turbo_read(int drive, int side) +{ + uint8_t dat = 0; + + int recv_data = 0; + int read_status = 0; + + dat = d86f_handler[drive].read_data(drive, side, d86f[drive].turbo_pos); + d86f[drive].turbo_pos++; + + if (d86f[drive].state == STATE_11_SCAN_DATA) + { + /* Scan/compare command. */ + recv_data = d86f_get_data(drive, 0); + d86f_compare_byte(drive, recv_data, dat); + } + else + { + if (d86f[drive].data_find.bytes_obtained < (128 << d86f[drive].last_sector.id.n)) + { + if (d86f[drive].state != STATE_16_VERIFY_DATA) + { + read_status = fdc_data(dat); + if (read_status == -1) + { + d86f[drive].dma_over++; + } + } + } + } + + if (d86f[drive].dma_over > 1) + { + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + d86f[drive].state = STATE_IDLE; + fdc_finishread(); + fdc_overrun(); + return; + } + + if (d86f[drive].turbo_pos >= (128 << d86f[drive].last_sector.id.n)) + { + /* CRC is valid. */ + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + if (d86f[drive].state == STATE_11_SCAN_DATA) + { + d86f[drive].state = STATE_IDLE; + fdc_sector_finishcompare((d86f[drive].satisfying_bytes == ((128 << ((uint32_t) d86f[drive].last_sector.id.n)) - 1)) ? 1 : 0); + } + else + { + d86f[drive].state = STATE_IDLE; + fdc_sector_finishread(); + } + } +} + +void d86f_turbo_write(int drive, int side) +{ + uint8_t dat = 0; + + dat = d86f_get_data(drive, 1); + d86f_handler[drive].write_data(drive, side, d86f[drive].turbo_pos, dat); + + d86f[drive].turbo_pos++; + + if (d86f[drive].turbo_pos >= (128 << d86f[drive].last_sector.id.n)) + { + /* We've written the data. */ + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + d86f[drive].state = STATE_IDLE; + d86f_handler[drive].writeback(drive); + fdc_sector_finishread(); + return; + } +} + +void d86f_turbo_format(int drive, int side, int nop) +{ + int dat; + int i = 0; + + uint16_t sc = 0; + uint16_t dtl = 0; + + sc = fdc_get_format_sectors(); + dtl = 128 << fdc_get_format_n(); + + if (d86f[drive].datac <= 3) + { + dat = fdc_getdata(0); + if (dat != -1) + { + dat &= 0xff; + } + if ((dat == -1) && (d86f[drive].datac < 3)) + { + dat = 0; + } + d86f[drive].format_sector_id.byte_array[d86f[drive].datac] = dat & 0xff; + if (d86f[drive].datac == 3) + { + fdc_stop_id_request(); + d86f_handler[drive].set_sector(drive, side, d86f[drive].format_sector_id.id.c, d86f[drive].format_sector_id.id.h, d86f[drive].format_sector_id.id.r, d86f[drive].format_sector_id.id.n); + } + } + else if (d86f[drive].datac == 4) + { + if (!nop) + { + for (i = 0; i < dtl; i++) + { + d86f_handler[drive].write_data(drive, side, i, d86f[drive].fill); + } + } + + d86f[drive].sector_count++; + } + + d86f[drive].datac++; + + if (d86f[drive].datac == 6) + { + d86f[drive].datac = 0; + + if (d86f[drive].sector_count < sc) + { + /* Sector within allotted amount. */ + fdc_request_next_sector_id(); + } + else + { + d86f[drive].state = STATE_IDLE; + d86f_format_turbo_finish(drive, side, nop); + } + } +} + +void d86f_turbo_poll(int drive, int side) +{ + switch(d86f[drive].state) + { + case STATE_0D_SPIN_TO_INDEX: + case STATE_0D_NOP_SPIN_TO_INDEX: + d86f[drive].sector_count = 0; + d86f[drive].datac = 5; + case STATE_02_SPIN_TO_INDEX: + d86f[drive].state++; + return; + case STATE_02_FIND_ID: + if (!(d86f[drive].sector_id_bit_field[side][fdc_get_read_track_sector().id.c][fdc_get_read_track_sector().id.h][fdc_get_read_track_sector().id.r] & (1 << fdc_get_read_track_sector().id.n))) + { + d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; + fdc_nosector(); + d86f[drive].state = STATE_IDLE; + return; + } + d86f[drive].last_sector.id.c = fdc_get_read_track_sector().id.c; + d86f[drive].last_sector.id.h = fdc_get_read_track_sector().id.h; + d86f[drive].last_sector.id.r = fdc_get_read_track_sector().id.r; + d86f[drive].last_sector.id.n = fdc_get_read_track_sector().id.n; + d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); + d86f[drive].turbo_pos = 0; + d86f[drive].state++; + return; + case STATE_05_FIND_ID: + case STATE_09_FIND_ID: + case STATE_06_FIND_ID: + case STATE_0C_FIND_ID: + case STATE_11_FIND_ID: + case STATE_16_FIND_ID: + if (!(d86f[drive].sector_id_bit_field[side][d86f[drive].req_sector.id.c][d86f[drive].req_sector.id.h][d86f[drive].req_sector.id.r] & (1 << d86f[drive].req_sector.id.n))) + { + d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; + fdc_nosector(); + d86f[drive].state = STATE_IDLE; + return; + } + d86f[drive].last_sector.id.c = d86f[drive].req_sector.id.c; + d86f[drive].last_sector.id.h = d86f[drive].req_sector.id.h; + d86f[drive].last_sector.id.r = d86f[drive].req_sector.id.r; + d86f[drive].last_sector.id.n = d86f[drive].req_sector.id.n; + d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); + case STATE_0A_FIND_ID: + d86f[drive].turbo_pos = 0; + d86f[drive].state++; + return; + case STATE_0A_READ_ID: + d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; + fdc_sectorid(d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n, 0, 0); + d86f[drive].state = STATE_IDLE; + break; + case STATE_02_READ_ID: + case STATE_05_READ_ID: + case STATE_09_READ_ID: + case STATE_06_READ_ID: + case STATE_0C_READ_ID: + case STATE_11_READ_ID: + case STATE_16_READ_ID: + d86f[drive].state++; + break; + case STATE_02_FIND_DATA: + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + case STATE_0C_FIND_DATA: + d86f[drive].state++; + break; + case STATE_02_READ_DATA: + case STATE_06_READ_DATA: + case STATE_0C_READ_DATA: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + d86f_turbo_read(drive, side); + break; + case STATE_05_WRITE_DATA: + case STATE_09_WRITE_DATA: + d86f_turbo_write(drive, side); + break; + case STATE_0D_FORMAT_TRACK: + d86f_turbo_format(drive, side, 0); + return; + case STATE_0D_NOP_FORMAT_TRACK: + d86f_turbo_format(drive, side, 1); + return; + case STATE_IDLE: + case STATE_SECTOR_NOT_FOUND: + default: + break; + } +} + void d86f_poll(int drive) { int side = 0; @@ -2035,6 +2321,12 @@ void d86f_poll(int drive) } } + if (fdd_get_turbo(drive) && (d86f[drive].version == 0x0063)) + { + d86f_turbo_poll(drive, side); + return; + } + if ((d86f[drive].state != STATE_02_SPIN_TO_INDEX) && (d86f[drive].state != STATE_0D_SPIN_TO_INDEX)) { d86f_get_bit(drive, side ^ 1); @@ -2337,6 +2629,8 @@ uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint16_t dataam_mfm = 0x4555; uint16_t datadam_mfm = 0x4A55; + d86f[drive].sector_id_bit_field[side][id_buf[0]][id_buf[1]][id_buf[2]] |= (1 << id_buf[3]); + mfm = d86f_is_mfm(drive); gap_fill = mfm ? 0x4E : 0xFF; diff --git a/src/disc_86f.h b/src/disc_86f.h index ec7e83c1e..bea967108 100644 --- a/src/disc_86f.h +++ b/src/disc_86f.h @@ -33,6 +33,7 @@ void d86f_readaddress(int drive, int side, int density); void d86f_format(int drive, int side, int density, uint8_t fill); void d86f_prepare_track_layout(int drive, int side); +void d86f_set_version(int drive, uint16_t version); #define length_gap0 80 #define length_gap1 50 @@ -59,3 +60,8 @@ extern int gap2_size[2]; extern int gap3_size[2]; extern int gap4_size[2]; #endif + +#define D86FVER 0x020B + +void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); +void d86f_zero_bit_field(int drive, int side); diff --git a/src/disc_fdi.c b/src/disc_fdi.c index af192b76f..219b29f21 100644 --- a/src/disc_fdi.c +++ b/src/disc_fdi.c @@ -22,6 +22,7 @@ #include #include "ibm.h" #include "disc.h" +#include "disc_86f.h" #include "disc_img.h" #include "disc_fdi.h" #include "fdc.h" @@ -254,6 +255,7 @@ void d86f_register_fdi(int drive) d86f_handler[drive].index_hole_pos = fdi_index_hole_pos; d86f_handler[drive].get_raw_size = fdi_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, D86FVER); } void fdi_load(int drive, wchar_t *fn) diff --git a/src/disc_imd.c b/src/disc_imd.c index d511dd46d..e8ca921e6 100644 --- a/src/disc_imd.c +++ b/src/disc_imd.c @@ -531,6 +531,9 @@ void imd_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); + d86f_zero_bit_field(drive, 0); + d86f_zero_bit_field(drive, 1); + for (side = 0; side < imd[drive].sides; side++) { track_rate = imd[drive].current_side_flags[side] & 7; @@ -601,6 +604,11 @@ void imd_seek(int drive, int track) imd_sector_to_buffer(drive, track, side, data, actual_sector, ssize); current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, deleted, bad_crc); track_buf_pos[side] += ssize; + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } else @@ -635,6 +643,11 @@ void imd_seek(int drive, int track) } track_buf_pos[side] += ssize; + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -746,6 +759,16 @@ void imd_writeback(int drive) } } +uint8_t imd_poll_read_data(int drive, int side, uint16_t pos) +{ + int type = imd[drive].current_data[side][0]; + if (!(type & 1)) + { + return 0xf6; /* Should never happen. */ + } + return imd[drive].current_data[side][pos + 1]; +} + void imd_poll_write_data(int drive, int side, uint16_t pos, uint8_t data) { int type = imd[drive].current_data[side][0]; @@ -777,6 +800,7 @@ void d86f_register_imd(int drive) d86f_handler[drive].side_flags = imd_side_flags; d86f_handler[drive].writeback = imd_writeback; d86f_handler[drive].set_sector = imd_set_sector; + d86f_handler[drive].read_data = imd_poll_read_data; d86f_handler[drive].write_data = imd_poll_write_data; d86f_handler[drive].format_conditions = imd_format_conditions; d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; @@ -785,4 +809,5 @@ void d86f_register_imd(int drive) d86f_handler[drive].index_hole_pos = null_index_hole_pos; d86f_handler[drive].get_raw_size = common_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); } diff --git a/src/disc_img.c b/src/disc_img.c index 4220e5af0..2429352a0 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -938,6 +938,9 @@ void img_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); + d86f_zero_bit_field(drive, 0); + d86f_zero_bit_field(drive, 1); + if (!img[drive].xdf_type || img[drive].is_cqm) { for (side = 0; side < img[drive].sides; side++) @@ -980,6 +983,11 @@ void img_seek(int drive, int track) img[drive].sector_pos_side[side][sr] = side; img[drive].sector_pos[side][sr] = (sr - 1) * ssize; current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[side][(sr - 1) * ssize], ssize, img[drive].gap2_size, img[drive].gap3_size, 0, 0); + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -1039,6 +1047,11 @@ void img_seek(int drive, int track) ssize = (128 << id[3]); current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &img[drive].track_data[buf_side][buf_pos], ssize, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0); } + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -1108,6 +1121,7 @@ void d86f_register_img(int drive) d86f_handler[drive].side_flags = img_side_flags; d86f_handler[drive].writeback = img_writeback; d86f_handler[drive].set_sector = img_set_sector; + d86f_handler[drive].read_data = img_poll_read_data; d86f_handler[drive].write_data = img_poll_write_data; d86f_handler[drive].format_conditions = img_format_conditions; d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; @@ -1116,4 +1130,5 @@ void d86f_register_img(int drive) d86f_handler[drive].index_hole_pos = null_index_hole_pos; d86f_handler[drive].get_raw_size = common_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); } diff --git a/src/disc_td0.c b/src/disc_td0.c index ac2cd9a6b..574dde621 100644 --- a/src/disc_td0.c +++ b/src/disc_td0.c @@ -1103,6 +1103,9 @@ void td0_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); + d86f_zero_bit_field(drive, 0); + d86f_zero_bit_field(drive, 1); + for (side = 0; side < td0[drive].sides; side++) { track_rate = td0[drive].current_side_flags[side] & 7; @@ -1141,6 +1144,11 @@ void td0_seek(int drive, int track) id[3] = td0[drive].sects[track][side][actual_sector].size; ssize = 128 << ((uint32_t) td0[drive].sects[track][side][actual_sector].size); current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][actual_sector].data, ssize, track_gap2, track_gap3, td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc); + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } else @@ -1164,6 +1172,11 @@ void td0_seek(int drive, int track) { current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc); } + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -1201,12 +1214,18 @@ void td0_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_ return; } +uint8_t td0_poll_read_data(int drive, int side, uint16_t pos) +{ + return td0[drive].sects[td0[drive].track][side][td0[drive].current_sector_index[side]].data[pos]; +} + void d86f_register_td0(int drive) { d86f_handler[drive].disk_flags = td0_disk_flags; d86f_handler[drive].side_flags = td0_side_flags; d86f_handler[drive].writeback = null_writeback; d86f_handler[drive].set_sector = td0_set_sector; + d86f_handler[drive].read_data = td0_poll_read_data; d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = null_format_conditions; d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; @@ -1215,4 +1234,5 @@ void d86f_register_td0(int drive) d86f_handler[drive].index_hole_pos = null_index_hole_pos; d86f_handler[drive].get_raw_size = common_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); } diff --git a/src/fdd.c b/src/fdd.c index dd6649ee2..1fb1e50ec 100644 --- a/src/fdd.c +++ b/src/fdd.c @@ -189,6 +189,11 @@ int fdd_track0(int drive) return !fdd[drive].track; } +int fdd_track(int drive) +{ + return fdd[drive].track; +} + void fdd_set_densel(int densel) { int i = 0; diff --git a/src/fdd.h b/src/fdd.h index e8de9db96..6a28743f4 100644 --- a/src/fdd.h +++ b/src/fdd.h @@ -49,3 +49,5 @@ char *fdd_getname(int type); char *fdd_get_internal_name(int type); int fdd_get_from_internal_name(char *s); + +int fdd_track(int drive); From 8a01fc7ef2e65fe9a9be4d964c1d8b3cfa5788d4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 26 Jul 2017 00:34:43 +0200 Subject: [PATCH 34/82] Properly fixed the configuration variable and section delete functions; Commented out the JEGA code. --- src/VIDEO/vid_ega.c | 25 +++++++++++++++++++++++++ src/VIDEO/vid_ega.h | 4 ++++ src/VIDEO/vid_ega_render.c | 2 ++ src/VIDEO/vid_ega_render.h | 2 ++ src/config.c | 33 +++++++++++++++++++++++++-------- src/config.h | 26 +++++++++++++++++++++----- 6 files changed, 79 insertions(+), 13 deletions(-) diff --git a/src/VIDEO/vid_ega.c b/src/VIDEO/vid_ega.c index 49cf3358a..33a3397bf 100644 --- a/src/VIDEO/vid_ega.c +++ b/src/VIDEO/vid_ega.c @@ -45,6 +45,7 @@ static int old_overscan_color = 0; int update_overscan = 0; +#ifdef JEGA uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */ uint8_t jfont_dbcs_16[DBCS16_LEN]; /* 65536 * 16 * 2 (* 8) */ @@ -146,6 +147,7 @@ void ega_jega_read_font(ega_t *ega) ega->font_index++; ega->RSTAT |= 0x02; } +#endif void ega_out(uint16_t addr, uint8_t val, void *p) { @@ -259,7 +261,11 @@ void ega_out(uint16_t addr, uint8_t val, void *p) return; case 0x3d1: case 0x3d5: +#ifdef JEGA if ((ega->crtcreg < 0xb9) || !ega->is_jega) +#else + if (ega->crtcreg < 0xb9) +#endif { crtcreg = ega->crtcreg & 0x1f; if (crtcreg <= 7 && ega->crtc[0x11] & 0x80) return; @@ -274,6 +280,7 @@ void ega_out(uint16_t addr, uint8_t val, void *p) } } } +#ifdef JEGA else { switch(ega->crtcreg) @@ -331,6 +338,7 @@ void ega_out(uint16_t addr, uint8_t val, void *p) break; } } +#endif break; } } @@ -391,11 +399,16 @@ uint8_t ega_in(uint16_t addr, void *p) return ega->crtcreg; case 0x3d1: case 0x3d5: +#ifdef JEGA if ((ega->crtcreg < 0xb9) || !ega->is_jega) +#else + if (ega->crtcreg < 0xb9) +#endif { crtcreg = ega->crtcreg & 0x1f; return ega->crtc[crtcreg]; } +#ifdef JEGA else { switch(ega->crtcreg) @@ -434,6 +447,8 @@ uint8_t ega_in(uint16_t addr, void *p) return 0x00; } } +#endif + return 0xff; case 0x3da: ega->attrff = 0; ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/ @@ -534,6 +549,7 @@ void ega_poll(void *p) { if (fullchange) { +#ifdef JEGA if (ega_jega_enabled(ega)) { ega_render_text_jega(ega, drawcursor); @@ -542,6 +558,9 @@ void ega_poll(void *p) { ega_render_text_standard(ega, drawcursor); } +#else + ega_render_text_standard(ega, drawcursor); +#endif } } else @@ -1016,7 +1035,9 @@ void ega_common_defaults(ega_t *ega) update_overscan = 0; +#ifdef JEGA ega->is_jega = 0; +#endif } void *ega_standalone_init() @@ -1138,6 +1159,7 @@ void *sega_standalone_init() return ega; } +#ifdef JEGA uint16_t chrtosht(FILE *fp) { uint16_t i, j; @@ -1243,6 +1265,7 @@ void *jega_standalone_init() return ega; } +#endif static int ega_standalone_available() { @@ -1337,6 +1360,7 @@ device_t sega_device = ega_config }; +#ifdef JEGA device_t jega_device = { "AX JEGA", @@ -1349,3 +1373,4 @@ device_t jega_device = NULL, ega_config }; +#endif diff --git a/src/VIDEO/vid_ega.h b/src/VIDEO/vid_ega.h index e7b30b32b..e9835d1fb 100644 --- a/src/VIDEO/vid_ega.h +++ b/src/VIDEO/vid_ega.h @@ -91,11 +91,13 @@ typedef struct ega_t int video_res_x, video_res_y, video_bpp; +#ifdef JEGA uint8_t RMOD1, RMOD2, RDAGS, RDFFB, RDFSB, RDFAP, RPESL, RPULP, RPSSC, RPSSU, RPSSL; uint8_t RPPAJ; uint8_t RCMOD, RCCLH, RCCLL, RCCSL, RCCEL, RCSKW, ROMSL, RSTAT; int is_jega, font_index; int chr_left, chr_wide; +#endif } ega_t; extern int update_overscan; @@ -113,6 +115,7 @@ extern device_t ega_device; extern device_t cpqega_device; extern device_t sega_device; +#ifdef JEGA #define SBCS 0 #define DBCS 1 #define ID_LEN 6 @@ -122,3 +125,4 @@ extern device_t sega_device; extern uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */ extern uint8_t jfont_dbcs_16[DBCS16_LEN]; /* 65536 * 16 * 2 (* 8) */ +#endif diff --git a/src/VIDEO/vid_ega_render.c b/src/VIDEO/vid_ega_render.c index 66c3f2f65..50ef6139e 100644 --- a/src/VIDEO/vid_ega_render.c +++ b/src/VIDEO/vid_ega_render.c @@ -146,6 +146,7 @@ void ega_render_text_standard(ega_t *ega, int drawcursor) } } +#ifdef JEGA static __inline int is_kanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); @@ -374,6 +375,7 @@ void ega_render_text_jega(ega_t *ega, int drawcursor) } } } +#endif void ega_render_2bpp_lowres(ega_t *ega) { diff --git a/src/VIDEO/vid_ega_render.h b/src/VIDEO/vid_ega_render.h index b833128a9..3ff9a5412 100644 --- a/src/VIDEO/vid_ega_render.h +++ b/src/VIDEO/vid_ega_render.h @@ -29,7 +29,9 @@ extern uint8_t edatlookup[4][4]; void ega_render_blank(ega_t *ega); void ega_render_text_standard(ega_t *ega, int drawcursor); +#ifdef JEGA void ega_render_text_jega(ega_t *ega, int drawcursor); +#endif void ega_render_2bpp_lowres(ega_t *ega); void ega_render_2bpp_highres(ega_t *ega); diff --git a/src/config.c b/src/config.c index 6bc9bf1f6..bc3d84ba2 100644 --- a/src/config.c +++ b/src/config.c @@ -1,5 +1,23 @@ -/* Copyright holders: Sarah Walker - * see COPYING for more details +/* + * 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. + * + * Configuration file handler. + * + * Version: @(#)config.c 1.0.0 2017/07/26 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * Overdoze, + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016-2017 Miran Grca. + * Copyright 2017-2017 Fred N. van Kempen. + * Copyright 2017-2017 Overdoze. * * NOTE: Forcing config files to be in Unicode encoding breaks it on * Windows XP, and possibly also Vista. Use -DANSI_CFG for use @@ -83,17 +101,14 @@ typedef struct entry_t #define list_delete(old, head) \ { \ - struct list_t *cur = head; \ struct list_t *next = head; \ \ - while (next->next != old) \ + while ((next)->next != old) \ { \ - cur = next; \ - next = next->next; \ + next = (next)->next; \ } \ \ - cur->next = next->next; \ - free(next); \ + (next)->next = (old)->next; \ } @@ -487,6 +502,7 @@ void config_delete_var(char *head, char *name) return; list_delete(&entry->list, §ion->entry_head); + free(entry); return; } @@ -504,6 +520,7 @@ void config_delete_section_if_empty(char *head) if (entries_num(section) == 0) { list_delete(§ion->list, &config_head); + free(section); } return; diff --git a/src/config.h b/src/config.h index 8d1db0b7b..a7c15383f 100644 --- a/src/config.h +++ b/src/config.h @@ -1,8 +1,24 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ - - +/* + * 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. + * + * Configuration file handler header. + * + * Version: @(#)config.h 1.0.0 2017/07/26 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * Overdoze, + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016-2017 Miran Grca. + * Copyright 2017-2017 Fred N. van Kempen. + * Copyright 2017-2017 Overdoze. + */ extern wchar_t config_file_default[256]; From edf2a5b24cd699517cee2e1c810cfbdde502f7b2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 26 Jul 2017 10:15:35 +0200 Subject: [PATCH 35/82] Fixed the turbo poller for cases like 720k floppy in 1.44M drive. --- src/disc_86f.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/disc_86f.c b/src/disc_86f.c index eac0b9128..06914a1c7 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -2193,6 +2193,22 @@ void d86f_turbo_format(int drive, int side, int nop) void d86f_turbo_poll(int drive, int side) { + if ((d86f[drive].state != STATE_IDLE) && (d86f[drive].state != STATE_SECTOR_NOT_FOUND) && ((d86f[drive].state & 0xF8) != 0xE8)) + { + if (!d86f_can_read_address(drive)) + { + /* if (fdc_get_bitcell_period() != d86f_get_bitcell_period(drive)) d86f_log("[%i, %i] Bitcell period mismatch (%i != %i)\n", drive, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive)); + if (!fdd_can_read_medium(real_drive(drive))) d86f_log("[%i, %i] Drive can not read medium (hole = %01X)\n", drive, side, d86f_hole(drive)); + if (fdc_is_mfm() != d86f_is_mfm(drive)) d86f_log("[%i, %i] Encoding mismatch\n", drive, side); + if (d86f_get_encoding(drive) > 1) d86f_log("[%i, %i] Image encoding (%s) not FM or MFM\n", drive, side, (d86f_get_encoding(drive) == 2) ? "M2FM" : "GCR"); */ + + d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; + fdc_noidam(); + d86f[drive].state = STATE_IDLE; + return; + } + } + switch(d86f[drive].state) { case STATE_0D_SPIN_TO_INDEX: @@ -2308,6 +2324,12 @@ void d86f_poll(int drive) } } + if (fdd_get_turbo(drive) && (d86f[drive].version == 0x0063)) + { + d86f_turbo_poll(drive, side); + return; + } + if ((d86f[drive].state != STATE_IDLE) && (d86f[drive].state != STATE_SECTOR_NOT_FOUND) && ((d86f[drive].state & 0xF8) != 0xE8)) { if (!d86f_can_read_address(drive)) @@ -2321,12 +2343,6 @@ void d86f_poll(int drive) } } - if (fdd_get_turbo(drive) && (d86f[drive].version == 0x0063)) - { - d86f_turbo_poll(drive, side); - return; - } - if ((d86f[drive].state != STATE_02_SPIN_TO_INDEX) && (d86f[drive].state != STATE_0D_SPIN_TO_INDEX)) { d86f_get_bit(drive, side ^ 1); From 658909e4168c6e5faef6154bb9217960d0642fc1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 26 Jul 2017 15:02:03 +0200 Subject: [PATCH 36/82] Fixed multiple bugs. --- src/WIN/win.c | 2 +- src/WIN/win_settings.c | 9 ++++----- src/disc_86f.c | 15 +++++++++++++++ src/disc_fdi.c | 4 ++++ src/disc_imd.c | 5 +++++ src/disc_img.c | 7 +++++++ src/disc_td0.c | 5 +++++ 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/WIN/win.c b/src/WIN/win.c index 66c20625c..d34465997 100644 --- a/src/WIN/win.c +++ b/src/WIN/win.c @@ -793,7 +793,7 @@ void create_floppy_tip(int part) } else { - _swprintf(tempTip, win_language_get_string_from_id(2179), drive + 1, wtext, discfns[drive]); + _swprintf(tempTip, win_language_get_string_from_id(IDS_2158), drive + 1, wtext, discfns[drive]); } if (sbTips[part] != NULL) diff --git a/src/WIN/win_settings.c b/src/WIN/win_settings.c index 32c7016b4..781a73e23 100644 --- a/src/WIN/win_settings.c +++ b/src/WIN/win_settings.c @@ -2500,7 +2500,6 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W char *big_buf; int b = 0; uint64_t r = 0; - int j = 0; switch (message) { @@ -2828,7 +2827,7 @@ hdd_add_file_open_error: } else { - for (j = 0; j < 16; j++) + for (i = 5; i < 16; i++) { if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19))) { @@ -3777,21 +3776,21 @@ static void cdrom_add_locations(HWND hdlg) h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2088), i); + wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2088), i); + wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2169), i >> 1, i & 1); + wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4097), i >> 1, i & 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } diff --git a/src/disc_86f.c b/src/disc_86f.c index 06914a1c7..95a03e86d 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -3390,6 +3390,7 @@ void d86f_load(int drive, wchar_t *fn) { /* File is WAY too small, abort. */ fclose(d86f[drive].f); + d86f[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -3399,6 +3400,7 @@ void d86f_load(int drive, wchar_t *fn) /* File is not of the valid format, abort. */ d86f_log("86F: Unrecognized magic bytes: %08X\n", magic); fclose(d86f[drive].f); + d86f[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -3421,6 +3423,7 @@ void d86f_load(int drive, wchar_t *fn) d86f_log("86F: Unrecognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); } fclose(d86f[drive].f); + d86f[drive].f = NULL; update_status_bar_icon_state(drive, 1); return; } @@ -3437,6 +3440,7 @@ void d86f_load(int drive, wchar_t *fn) { /* File too small, abort. */ fclose(d86f[drive].f); + d86f[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -3459,6 +3463,7 @@ void d86f_load(int drive, wchar_t *fn) { d86f_log("86F: CRC64 error\n"); fclose(d86f[drive].f); + d86f[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -3470,6 +3475,7 @@ void d86f_load(int drive, wchar_t *fn) memcpy(d86f[drive].original_file_name, fn, (wcslen(fn) << 1) + 2); fclose(d86f[drive].f); + d86f[drive].f = NULL; d86f[drive].f = _wfopen(temp_file_name, L"wb"); if (!d86f[drive].f) @@ -3500,6 +3506,7 @@ void d86f_load(int drive, wchar_t *fn) fclose(tf); fclose(d86f[drive].f); + d86f[drive].f = NULL; if (!temp) { @@ -3517,6 +3524,7 @@ void d86f_load(int drive, wchar_t *fn) /* Zoned disk. */ d86f_log("86F: Disk is zoned (Apple or Sony)\n"); fclose(d86f[drive].f); + d86f[drive].f = NULL; if (d86f[drive].is_compressed) { _wremove(temp_file_name); @@ -3530,6 +3538,7 @@ void d86f_load(int drive, wchar_t *fn) /* Zone type is not 0 but the disk is fixed-RPM. */ d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); fclose(d86f[drive].f); + d86f[drive].f = NULL; if (d86f[drive].is_compressed) { _wremove(temp_file_name); @@ -3547,6 +3556,7 @@ void d86f_load(int drive, wchar_t *fn) if (writeprot[drive]) { fclose(d86f[drive].f); + d86f[drive].f = NULL; if (d86f[drive].is_compressed) { @@ -3567,6 +3577,7 @@ void d86f_load(int drive, wchar_t *fn) /* File has no track 0 side 0, abort. */ d86f_log("86F: No Track 0 side 0\n"); fclose(d86f[drive].f); + d86f[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -3576,6 +3587,7 @@ void d86f_load(int drive, wchar_t *fn) /* File is 2-sided but has no track 0 side 1, abort. */ d86f_log("86F: No Track 0 side 1\n"); fclose(d86f[drive].f); + d86f[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -3657,7 +3669,10 @@ void d86f_close(int drive) memcpy(temp_file_name, drive ? nvr_concat(L"TEMP$$$1.$$$") : nvr_concat(L"TEMP$$$0.$$$"), 26); if (d86f[drive].f) + { fclose(d86f[drive].f); + d86f[drive].f = NULL; + } if (d86f[drive].is_compressed) _wremove(temp_file_name); } diff --git a/src/disc_fdi.c b/src/disc_fdi.c index 219b29f21..e23862d65 100644 --- a/src/disc_fdi.c +++ b/src/disc_fdi.c @@ -280,6 +280,7 @@ void fdi_load(int drive, wchar_t *fn) /* This is a Japanese FDI file. */ pclog("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n"); fclose(fdi[drive].f); + fdi[drive].f = NULL; img_load(drive, fn); return; } @@ -303,7 +304,10 @@ void fdi_close(int drive) if (fdi[drive].h) fdi2raw_header_free(fdi[drive].h); if (fdi[drive].f) + { fclose(fdi[drive].f); + fdi[drive].f = NULL; + } } void fdi_seek(int drive, int track) diff --git a/src/disc_imd.c b/src/disc_imd.c index e8ca921e6..2017d1e96 100644 --- a/src/disc_imd.c +++ b/src/disc_imd.c @@ -110,6 +110,7 @@ void imd_load(int drive, wchar_t *fn) { pclog("IMD: Not a valid ImageDisk image\n"); fclose(imd[drive].f); + imd[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -131,6 +132,7 @@ void imd_load(int drive, wchar_t *fn) { pclog("IMD: No ASCII EOF character\n"); fclose(imd[drive].f); + imd[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -144,6 +146,7 @@ void imd_load(int drive, wchar_t *fn) { pclog("IMD: File ends after ASCII EOF character\n"); fclose(imd[drive].f); + imd[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -263,6 +266,7 @@ void imd_load(int drive, wchar_t *fn) /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ pclog("IMD: Unable to fit the %i sectors in a track\n", track_spt); fclose(imd[drive].f); + imd[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -301,6 +305,7 @@ void imd_close(int drive) memset(&(imd[drive].tracks[i][1]), 0, sizeof(imd_track_t)); } fclose(imd[drive].f); + imd[drive].f = NULL; } } diff --git a/src/disc_img.c b/src/disc_img.c index 2429352a0..594807dc4 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -358,6 +358,7 @@ void img_load(int drive, wchar_t *fn) } writeprot[drive] = 1; } + pclog("Floppy %i file pointer: %08X\n", drive, img[drive].f); if (ui_writeprot[drive]) { writeprot[drive] = 1; @@ -752,6 +753,7 @@ jump_if_fdf: { pclog("Image is bigger than can fit on an ED floppy, ejecting...\n"); fclose(img[drive].f); + img[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -814,6 +816,7 @@ jump_if_fdf: { pclog("Image is bigger than can fit on an ED floppy, ejecting...\n"); fclose(img[drive].f); + img[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -831,6 +834,7 @@ jump_if_fdf: { pclog("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); fclose(img[drive].f); + img[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -863,7 +867,10 @@ void img_close(int drive) { d86f_unregister(drive); if (img[drive].f) + { fclose(img[drive].f); + img[drive].f = NULL; + } if (img[drive].disk_data) free(img[drive].disk_data); } diff --git a/src/disc_td0.c b/src/disc_td0.c index 574dde621..af9963e40 100644 --- a/src/disc_td0.c +++ b/src/disc_td0.c @@ -545,6 +545,7 @@ void td0_load(int drive, wchar_t *fn) { pclog("TD0: Not a valid Teledisk image\n"); fclose(td0[drive].f); + td0[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -560,6 +561,7 @@ void td0_load(int drive, wchar_t *fn) { pclog("TD0: Failed to initialize\n"); fclose(td0[drive].f); + td0[drive].f = NULL; memset(discfns[drive], 0, sizeof(discfns[drive])); return; } @@ -607,7 +609,10 @@ void td0_close(int drive) } if (td0[drive].f) + { fclose(td0[drive].f); + td0[drive].f = NULL; + } } uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm) From bb053cee5dec48431274bc60d0acd1d44b713686 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 26 Jul 2017 15:10:52 +0200 Subject: [PATCH 37/82] Removed some excess logging. --- src/disc_img.c | 1 - src/serial_old.c | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/disc_img.c b/src/disc_img.c index 594807dc4..8c78a5180 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -358,7 +358,6 @@ void img_load(int drive, wchar_t *fn) } writeprot[drive] = 1; } - pclog("Floppy %i file pointer: %08X\n", drive, img[drive].f); if (ui_writeprot[drive]) { writeprot[drive] = 1; diff --git a/src/serial_old.c b/src/serial_old.c index c6bc83e4c..7dbb3e928 100644 --- a/src/serial_old.c +++ b/src/serial_old.c @@ -264,7 +264,7 @@ void serial_remove(int port) return; } - pclog("Removing serial port %i at %04X...\n", port, base_address[port - 1]); + /* pclog("Removing serial port %i at %04X...\n", port, base_address[port - 1]); */ switch(port) { @@ -281,7 +281,7 @@ void serial_remove(int port) void serial_setup(int port, uint16_t addr, int irq) { - pclog("Adding serial port %i at %04X...\n", port, addr); + /* pclog("Adding serial port %i at %04X...\n", port, addr); */ switch(port) { @@ -322,7 +322,7 @@ void serial_init(void) if (serial_enabled[0]) { - pclog("Adding serial port 1...\n"); + /* pclog("Adding serial port 1...\n"); */ memset(&serial1, 0, sizeof(serial1)); io_sethandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); serial1.irq = 4; @@ -331,7 +331,7 @@ void serial_init(void) } if (serial_enabled[1]) { - pclog("Adding serial port 2...\n"); + /* pclog("Adding serial port 2...\n"); */ memset(&serial2, 0, sizeof(serial2)); io_sethandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); serial2.irq = 3; From 000b7d8a27dc85d9983f59676367695b2eb41249 Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Wed, 26 Jul 2017 16:29:51 +0300 Subject: [PATCH 38/82] Add compilation instructions to README.md --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 7c07f7b76..7fc07312b 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,20 @@ Keep in touch with the 86Box community: [![Visit our IRC channel](https://kiwiirc.com/buttons/irc.rol.im/softhistory.png)](https://kiwiirc.com/client/irc.rol.im/?nick=86box|?#softhistory) [![Visit our Discord server](https://discordapp.com/api/guilds/262614059009048590/embed.png)](https://discord.gg/Es3TnUH) + +--- +# Compilation +In order to compile 86Box from this repository, please follow this step-by-step guide: +1) Download the development environment from http://tinyurl.com/pcemude. Afterwards, extract it to your desired location. Of course, also clone the repository in your desired location. Downloading ZIPs is not recommended, as it makes it more inconvenient to keep the code up-to-date. To avoid issues, make sure neither path has spaces in it. +2) In the extracted environment folder, you will find a script called **mingw32_shell.bat**. Launch it. There are other shell launching scripts in there, but you should not use them. +3) Once launched, run **pacman -Syuu** in order to update the environment. Depending on the state of the downloaded DE, you may need to run it twice (once initially, and then again after re-entering the environment). Make sure to keep the enviroment up-to-date by re-running the command periodically. +4) Once the environment is fully updated, **cd** into your cloned **86box\src** directory. +5) Run **make -j*N* -fmakefile.mingw** to start the actual compilation process. Substitute *N* with the number of threads you want to use for the compilation process. The optimal number depends entirely on your processor, and it is up to you to determine the optimal number. A good starting point is the total number of threads (AKA Logical Processors) you have available. +6) If the compilation succeeded (which it almost always should), you will find 86box.exe in the src directory. +7) In order to test your fresh build, replace the 86box.exe in your current 86box enviroment with your freshly built one. If you do not have a pre-existing 86box environment, download the latest successful build from ci.86box.net, and the ROM set from http://tinyurl.com/roms2017. +8) Enjoy using and testing the emulator! :) + +If you encounter issues at any step or have additional questions, please join the IRC channel and wait patiently for someone to help you. + +In order to keep the clone up-to-date, make sure to pull any new changes periodically. With command line git, this is achieved by running **git pull** within the clone directory. If you are using TortoiseGit, the same is achieved by selecting the pull option from the TortoiseGit right-click menu in Explorer. + From 805ee8f1df57055e2cc1d349639dae9c3c320c1c Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Wed, 26 Jul 2017 16:32:20 +0300 Subject: [PATCH 39/82] Add compilation instructions to README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fc07312b..e913b3291 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ In order to compile 86Box from this repository, please follow this step-by-step 4) Once the environment is fully updated, **cd** into your cloned **86box\src** directory. 5) Run **make -j*N* -fmakefile.mingw** to start the actual compilation process. Substitute *N* with the number of threads you want to use for the compilation process. The optimal number depends entirely on your processor, and it is up to you to determine the optimal number. A good starting point is the total number of threads (AKA Logical Processors) you have available. 6) If the compilation succeeded (which it almost always should), you will find 86box.exe in the src directory. -7) In order to test your fresh build, replace the 86box.exe in your current 86box enviroment with your freshly built one. If you do not have a pre-existing 86box environment, download the latest successful build from ci.86box.net, and the ROM set from http://tinyurl.com/roms2017. +7) In order to test your fresh build, replace the 86box.exe in your current 86box enviroment with your freshly built one. If you do not have a pre-existing 86box environment, download the latest successful build from http://ci.86box.net, and the ROM set from http://tinyurl.com/roms2017. 8) Enjoy using and testing the emulator! :) If you encounter issues at any step or have additional questions, please join the IRC channel and wait patiently for someone to help you. From c595684be027b7238feae9f7d5250dc5a539548a Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Wed, 26 Jul 2017 16:37:03 +0300 Subject: [PATCH 40/82] Add compilation instructions to README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e913b3291..ffc2de839 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ In order to compile 86Box from this repository, please follow this step-by-step 3) Once launched, run **pacman -Syuu** in order to update the environment. Depending on the state of the downloaded DE, you may need to run it twice (once initially, and then again after re-entering the environment). Make sure to keep the enviroment up-to-date by re-running the command periodically. 4) Once the environment is fully updated, **cd** into your cloned **86box\src** directory. 5) Run **make -j*N* -fmakefile.mingw** to start the actual compilation process. Substitute *N* with the number of threads you want to use for the compilation process. The optimal number depends entirely on your processor, and it is up to you to determine the optimal number. A good starting point is the total number of threads (AKA Logical Processors) you have available. -6) If the compilation succeeded (which it almost always should), you will find 86box.exe in the src directory. -7) In order to test your fresh build, replace the 86box.exe in your current 86box enviroment with your freshly built one. If you do not have a pre-existing 86box environment, download the latest successful build from http://ci.86box.net, and the ROM set from http://tinyurl.com/roms2017. +6) If the compilation succeeded (which it almost always should), you will find **86Box.exe** in the src directory. +7) In order to test your fresh build, replace the **86Box.exe** in your current 86Box enviroment with your freshly built one. If you do not have a pre-existing 86Box environment, download the latest successful build from http://ci.86box.net, and the ROM set from http://tinyurl.com/roms2017. 8) Enjoy using and testing the emulator! :) If you encounter issues at any step or have additional questions, please join the IRC channel and wait patiently for someone to help you. From f8251b18d8f42ace2b0a38ba8e1ff84c739ba4d0 Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Wed, 26 Jul 2017 16:41:00 +0300 Subject: [PATCH 41/82] Add compilation instructions in README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ffc2de839..f6ba5eacf 100644 --- a/README.md +++ b/README.md @@ -20,5 +20,4 @@ In order to compile 86Box from this repository, please follow this step-by-step If you encounter issues at any step or have additional questions, please join the IRC channel and wait patiently for someone to help you. -In order to keep the clone up-to-date, make sure to pull any new changes periodically. With command line git, this is achieved by running **git pull** within the clone directory. If you are using TortoiseGit, the same is achieved by selecting the pull option from the TortoiseGit right-click menu in Explorer. From ede7c981406f00ae435a836ff067015936407ea9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Jul 2017 15:32:59 +0200 Subject: [PATCH 42/82] The short name of the ASUS P/I-P55T2P4 is now the correct p55t2p4 and not p55r2p4. Sorry for the typo. --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 4e6887441..e37fae1db 100644 --- a/src/model.c +++ b/src/model.c @@ -221,7 +221,7 @@ MODEL models[] = {"[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_acerm3a_init, NULL }, {"[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_acerv35n_init, NULL }, {"[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_ap53_init, NULL }, - {"[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55r2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p55t2p4_init, NULL }, + {"[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p55t2p4_init, NULL }, {"[Socket 7 HX] ASUS P/I-P55T2S", ROM_P55T2S, "p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p55t2s_init, NULL }, {"[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p55tvp4_init, NULL }, From c8b04398b60aa0594c86e301ee093a3e9cc948f9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Jul 2017 15:35:49 +0200 Subject: [PATCH 43/82] The configuration parser now detects the old p55r2p4 typo and silently corrects it to p55t2p4, ensuring that previous configurations do not break. --- src/config.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/config.c b/src/config.c index bc3d84ba2..105274cbb 100644 --- a/src/config.c +++ b/src/config.c @@ -873,7 +873,14 @@ static void loadconfig_machine(void) p = config_get_string(cat, "model", NULL); if (p != NULL) + { model = model_get_model_from_internal_name(p); + /* Detect the old model typo and fix it, so that old configurations don't braek. */ + if (strcmp(model, "p55r2p4") == 0) + { + model[3] = 't'; + } + } else model = 0; if (model >= model_count()) From c211c53d323a07a5c8ea0043c32b3f29ba45065a Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Jul 2017 15:38:07 +0200 Subject: [PATCH 44/82] Fixed the compile-breaking mistake. --- src/config.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 105274cbb..1dbbd28f6 100644 --- a/src/config.c +++ b/src/config.c @@ -874,11 +874,14 @@ static void loadconfig_machine(void) p = config_get_string(cat, "model", NULL); if (p != NULL) { - model = model_get_model_from_internal_name(p); /* Detect the old model typo and fix it, so that old configurations don't braek. */ - if (strcmp(model, "p55r2p4") == 0) + if (strcmp(p, "p55r2p4") == 0) { - model[3] = 't'; + model = model_get_model_from_internal_name("p55t2p4"); + } + else + { + model = model_get_model_from_internal_name(p); } } else From 306ae2fd32b49077e5d874e699ba61219ab23ccc Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Jul 2017 17:14:52 +0200 Subject: [PATCH 45/82] Added ability to disable floppy image BPB checking per drive, enabled by default. --- src/WIN/86Box.rc | 7 ++++-- src/WIN/resource.h | 26 +++++++++++--------- src/WIN/win_settings.c | 55 +++++++++++++++++++++++++++++++++++++++++- src/config.c | 18 ++++++++++++++ src/disc_img.c | 2 +- src/fdd.c | 12 +++++++++ src/fdd.h | 2 ++ 7 files changed, 106 insertions(+), 16 deletions(-) diff --git a/src/WIN/86Box.rc b/src/WIN/86Box.rc index 04d628200..05381bd48 100644 --- a/src/WIN/86Box.rc +++ b/src/WIN/86Box.rc @@ -461,8 +461,10 @@ BEGIN COMBOBOX IDC_COMBO_FD_TYPE,33,85,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Type:",IDT_1738,7,86,24,8 - CONTROL "Turbo timings (no accuracy)",IDC_CHECKTURBO,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,131,86,129,10 + CONTROL "Turbo timings",IDC_CHECKTURBO,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,131,86,64,10 + CONTROL "Check BPB",IDC_CHECKBPB,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,196,86,64,10 CONTROL "List1",IDC_LIST_CDROM_DRIVES,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,116,253,60 @@ -838,6 +840,7 @@ BEGIN IDS_2167 "&Reload previous image" IDS_2168 "&Image..." IDS_2169 "Image (&Write-protected)..." + IDS_2170 "Check BPB" IDS_3072 "None" IDS_3073 "[Bus] Bus mouse" diff --git a/src/WIN/resource.h b/src/WIN/resource.h index 41206cb1f..41b933e7f 100644 --- a/src/WIN/resource.h +++ b/src/WIN/resource.h @@ -163,17 +163,18 @@ #define IDC_LIST_FLOPPY_DRIVES 1151 #define IDC_COMBO_FD_TYPE 1152 #define IDC_CHECKTURBO 1153 -#define IDC_BUTTON_FDD_ADD 1154 // status bar menu -#define IDC_BUTTON_FDD_EDIT 1155 // status bar menu -#define IDC_BUTTON_FDD_REMOVE 1156 // status bar menu -#define IDC_LIST_CDROM_DRIVES 1157 -#define IDC_COMBO_CD_BUS 1158 -#define IDC_COMBO_CD_ID 1159 -#define IDC_COMBO_CD_LUN 1160 -#define IDC_COMBO_CD_CHANNEL_IDE 1161 -#define IDC_BUTTON_CDROM_ADD 1162 // status bar menu -#define IDC_BUTTON_CDROM_EDIT 1163 // status bar menu -#define IDC_BUTTON_CDROM_REMOVE 1164 // status bar menu +#define IDC_CHECKBPB 1154 +#define IDC_BUTTON_FDD_ADD 1155 // status bar menu +#define IDC_BUTTON_FDD_EDIT 1156 // status bar menu +#define IDC_BUTTON_FDD_REMOVE 1157 // status bar menu +#define IDC_LIST_CDROM_DRIVES 1158 +#define IDC_COMBO_CD_BUS 1159 +#define IDC_COMBO_CD_ID 1160 +#define IDC_COMBO_CD_LUN 1161 +#define IDC_COMBO_CD_CHANNEL_IDE 1162 +#define IDC_BUTTON_CDROM_ADD 1163 // status bar menu +#define IDC_BUTTON_CDROM_EDIT 1164 // status bar menu +#define IDC_BUTTON_CDROM_REMOVE 1165 // status bar menu /* For the DeviceConfig code, re-do later. */ @@ -319,6 +320,7 @@ #define IDS_2167 2167 // "RLL" #define IDS_2168 2168 // "IDE (PIO-only)" #define IDS_2169 2169 // "%01i:%01i" +#define IDS_2170 2170 // "%01i:%01i" #define IDS_3072 3072 #define IDS_3073 3073 @@ -391,7 +393,7 @@ #define IDS_LANG_ENUS IDS_6144 -#define STRINGS_NUM_2048 122 +#define STRINGS_NUM_2048 123 #define STRINGS_NUM_3072 11 #define STRINGS_NUM_4096 20 #define STRINGS_NUM_4352 7 diff --git a/src/WIN/win_settings.c b/src/WIN/win_settings.c index 781a73e23..7b127e17e 100644 --- a/src/WIN/win_settings.c +++ b/src/WIN/win_settings.c @@ -78,6 +78,7 @@ static hard_disk_t temp_hdc[HDC_NUM]; /* Removable devices category */ static int temp_fdd_types[FDD_NUM]; static int temp_fdd_turbo[FDD_NUM]; +static int temp_fdd_check_bpb[FDD_NUM]; static cdrom_drive_t temp_cdrom_drives[CDROM_NUM]; static HWND hwndParentDialog, hwndChildDialog; @@ -158,6 +159,7 @@ static void win_settings_init(void) { temp_fdd_types[i] = fdd_get_type(i); temp_fdd_turbo[i] = fdd_get_turbo(i); + temp_fdd_check_bpb[i] = fdd_get_check_bpb(i); } memcpy(temp_cdrom_drives, cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); } @@ -224,6 +226,7 @@ static int win_settings_changed(void) { i = i || (temp_fdd_types[j] != fdd_get_type(j)); i = i || (temp_fdd_turbo[j] != fdd_get_turbo(j)); + i = i || (temp_fdd_check_bpb[j] != fdd_get_check_bpb(j)); } i = i || memcmp(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); @@ -327,6 +330,7 @@ static void win_settings_save(void) { fdd_set_type(i, temp_fdd_types[i]); fdd_set_turbo(i, temp_fdd_turbo[i]); + fdd_set_check_bpb(i, temp_fdd_check_bpb[i]); } memcpy(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); @@ -3531,6 +3535,16 @@ static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) { return FALSE; } + + lvI.iSubItem = 2; + lvI.pszText = win_language_get_string_from_id(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + { + return FALSE; + } } return TRUE; @@ -3603,7 +3617,7 @@ static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) lvc.iSubItem = 1; lvc.pszText = win_language_get_string_from_id(IDS_2059); - lvc.cx = 100; + lvc.cx = 50; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) @@ -3611,6 +3625,16 @@ static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) return FALSE; } + lvc.iSubItem = 2; + lvc.pszText = win_language_get_string_from_id(IDS_2170); + + lvc.cx = 75; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 2, &lvc) == -1) + { + return FALSE; + } return TRUE; } @@ -3710,6 +3734,16 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) { return; } + + lvI.iSubItem = 2; + lvI.pszText = win_language_get_string_from_id(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + { + return; + } } static void win_settings_cdrom_drives_update_item(HWND hwndList, int i) @@ -3897,6 +3931,9 @@ static BOOL CALLBACK win_settings_removable_devices_proc(HWND hdlg, UINT message h = GetDlgItem(hdlg, IDC_CHECKTURBO); SendMessage(h, BM_SETCHECK, temp_fdd_turbo[fdlv_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKBPB); + SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[fdlv_current_sel], 0); + cdlv_current_sel = 0; h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); win_settings_cdrom_drives_init_columns(h); @@ -3958,6 +3995,8 @@ static BOOL CALLBACK win_settings_removable_devices_proc(HWND hdlg, UINT message SendMessage(h, CB_SETCURSEL, temp_fdd_types[fdlv_current_sel], 0); h = GetDlgItem(hdlg, IDC_CHECKTURBO); SendMessage(h, BM_SETCHECK, temp_fdd_turbo[fdlv_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKBPB); + SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[fdlv_current_sel], 0); rd_ignore_change = 0; } else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) @@ -4035,6 +4074,20 @@ static BOOL CALLBACK win_settings_removable_devices_proc(HWND hdlg, UINT message rd_ignore_change = 0; return FALSE; + case IDC_CHECKBPB: + if (rd_ignore_change) + { + return FALSE; + } + + rd_ignore_change = 1; + h = GetDlgItem(hdlg, IDC_CHECKBPB); + temp_fdd_check_bpb[fdlv_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_update_item(h, fdlv_current_sel); + rd_ignore_change = 0; + return FALSE; + case IDC_COMBO_CD_BUS: if (rd_ignore_change) { diff --git a/src/config.c b/src/config.c index 1dbbd28f6..8af6785fe 100644 --- a/src/config.c +++ b/src/config.c @@ -1547,6 +1547,8 @@ static void loadconfig_removable_devices(void) ui_writeprot[c] = !!config_get_int(cat, temps, 0); sprintf(temps, "fdd_%02i_turbo", c + 1); fdd_set_turbo(c, !!config_get_int(cat, temps, 0)); + sprintf(temps, "fdd_%02i_check_bpb", c + 1); + fdd_set_check_bpb(c, !!config_get_int(cat, temps, 1)); /* Check, whether each value is default, if yes, delete it so that only non-default values will later be saved. */ if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) @@ -1572,6 +1574,12 @@ static void loadconfig_removable_devices(void) sprintf(temps, "fdd_%02i_turbo", c + 1); config_delete_var(cat, temps); } + + if (fdd_get_check_bpb(c) == 1) + { + sprintf(temps, "fdd_%02i_check_bpb", c + 1); + config_delete_var(cat, temps); + } } memset(temps, 0, 512); @@ -2455,6 +2463,16 @@ static void saveconfig_removable_devices(void) { config_set_int(cat, temps, fdd_get_turbo(c)); } + + sprintf(temps, "fdd_%02i_check_bpb", c + 1); + if (fdd_get_check_bpb(c) == 1) + { + config_delete_var(cat, temps); + } + else + { + config_set_int(cat, temps, fdd_get_check_bpb(c)); + } } memset(temps, '\0', sizeof(temps)); diff --git a/src/disc_img.c b/src/disc_img.c index 8c78a5180..64eb40fe7 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -710,7 +710,7 @@ jump_if_fdf: pclog("BPB reports %i sides and %i bytes per sector (%i sectors total)\n", bpb_sides, bpb_bps, bpb_total); - if (((bpb_sides < 1) || (bpb_sides > 2) || !bps_is_valid(bpb_bps) || !first_byte_is_valid(first_byte)) && !fdi && !cqm) + if ((((bpb_sides < 1) || (bpb_sides > 2) || !bps_is_valid(bpb_bps) || !first_byte_is_valid(first_byte)) && !fdi && !cqm) || !fdd_get_check_bpb(drive)) { /* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably not a BPB at all, so we have to guess the parameters from file size. */ diff --git a/src/fdd.c b/src/fdd.c index 1fb1e50ec..2fb24c5ec 100644 --- a/src/fdd.c +++ b/src/fdd.c @@ -32,6 +32,8 @@ static struct int head; int turbo; + + int check_bpb; } fdd[FDD_NUM]; /* Flags: @@ -329,6 +331,16 @@ int fdd_get_turbo(int drive) return fdd[drive].turbo; } +void fdd_set_check_bpb(int drive, int check_bpb) +{ + fdd[drive].check_bpb = check_bpb; +} + +int fdd_get_check_bpb(int drive) +{ + return fdd[drive].check_bpb; +} + int fdd_get_densel(int drive) { if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL) diff --git a/src/fdd.h b/src/fdd.h index 6a28743f4..3caf5250f 100644 --- a/src/fdd.h +++ b/src/fdd.h @@ -32,6 +32,8 @@ void fdd_set_head(int drive, int head); int fdd_get_head(int drive); void fdd_set_turbo(int drive, int turbo); int fdd_get_turbo(int drive); +void fdd_set_check_bpb(int drive, int check_bpb); +int fdd_get_check_bpb(int drive); void fdd_set_type(int drive, int type); int fdd_get_type(int drive); From fcdd732d273227fd2895032d3cb14cc60d8fb135 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 27 Jul 2017 21:35:43 +0200 Subject: [PATCH 46/82] Virge changes: Removed excess logging. Fixed ViRGE paintbrush glitches with plain ViRGE drivers on Win3.1 and OS/2's WinOS/2. Updated the ViRGE/VX to use the new PCI set. Removed useless IRQ configuration as it's now handled by the new PCI IRQ set. --- src/VIDEO/vid_s3_virge.c | 66 +++++++++------------------------------- 1 file changed, 14 insertions(+), 52 deletions(-) diff --git a/src/VIDEO/vid_s3_virge.c b/src/VIDEO/vid_s3_virge.c index e81dcf330..997b707e4 100644 --- a/src/VIDEO/vid_s3_virge.c +++ b/src/VIDEO/vid_s3_virge.c @@ -638,7 +638,7 @@ static void s3_virge_updatemapping(virge_t *virge) return; } - pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); + //pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ { case 0x0: /*128k at A0000*/ @@ -661,7 +661,7 @@ static void s3_virge_updatemapping(virge_t *virge) virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); + //pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ { switch (svga->crtc[0x58] & 3) @@ -681,7 +681,7 @@ static void s3_virge_updatemapping(virge_t *virge) } virge->linear_base &= ~(virge->linear_size - 1); svga->linear_base = virge->linear_base; - pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); + //pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); if (virge->linear_base == 0xa0000) { mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); @@ -697,7 +697,7 @@ static void s3_virge_updatemapping(virge_t *virge) svga->fb_only = 0; } - pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); + //pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); if (svga->crtc[0x53] & 0x10) /*Old MMIO*/ { if (svga->crtc[0x53] & 0x20) @@ -1350,16 +1350,20 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) svga_t *svga = &virge->svga; reg_writes++; + pclog("Write Address %x\n", addr & 0xe000); + if ((addr & 0xfffc) < 0x8000) { s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); } - else if ((addr & 0xe000) == 0xa000) - { - s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); - } else switch (addr & 0xfffc) { + case 0: + s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x8180: virge->streams.pri_ctrl = val; svga_recalctimings(svga); @@ -3789,7 +3793,6 @@ static void *s3_virge_init() virge->pci_regs[6] = 0; virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3c] = device_get_config_int("irq"); virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; virge->pci_regs[0x3f] = 0xff; @@ -3884,7 +3887,6 @@ static void *s3_virge_988_init() virge->pci_regs[6] = 0; virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3c] = device_get_config_int("irq"); virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; virge->pci_regs[0x3f] = 0xff; @@ -3911,7 +3913,7 @@ static void *s3_virge_988_init() virge->is_375 = 0; - pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); + virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); virge->wake_render_thread = thread_create_event(); virge->wake_main_thread = thread_create_event(); @@ -3979,7 +3981,6 @@ static void *s3_virge_375_init(wchar_t *romfn) virge->pci_regs[6] = 0; virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3c] = device_get_config_int("irq"); virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; virge->pci_regs[0x3f] = 0xff; @@ -4007,7 +4008,7 @@ static void *s3_virge_375_init(wchar_t *romfn) virge->is_375 = 1; - pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); + virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); virge->wake_render_thread = thread_create_event(); virge->wake_main_thread = thread_create_event(); @@ -4125,45 +4126,6 @@ static device_config_t s3_virge_config[] = } } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - .default_int = 3 - }, { "bilinear", "Bilinear filtering", CONFIG_BINARY, "", 1 }, From 7199ac2450c0e954761131a51e744dd575737c9e Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 27 Jul 2017 21:42:00 +0200 Subject: [PATCH 47/82] S3 ViRGE changes: Removed excessive MMIO logging. Updated the VX variant to use the new PCI set. Removed useless manual IRQ configuration. Fixed paintbrush glitches with standalone OS/2 WinOS2 drivers and standalone Win3.1 drivers. --- src/vid_s3_virge.c | 4190 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4190 insertions(+) create mode 100644 src/vid_s3_virge.c diff --git a/src/vid_s3_virge.c b/src/vid_s3_virge.c new file mode 100644 index 000000000..997b707e4 --- /dev/null +++ b/src/vid_s3_virge.c @@ -0,0 +1,4190 @@ +/* Copyright holders: Sarah Walker + see COPYING for more details +*/ +/*S3 ViRGE emulation*/ +#include +#include "../ibm.h" +#include "../io.h" +#include "../mem.h" +#include "../pci.h" +#include "../rom.h" +#include "../device.h" +#include "../win/plat_thread.h" +#include "video.h" +#include "vid_s3_virge.h" +#include "vid_svga.h" +#include "vid_svga_render.h" + + +static uint64_t virge_time = 0; +static uint64_t status_time = 0; +static int reg_writes = 0, reg_reads = 0; + +static int dither[4][4] = +{ + {0, 4, 1, 5}, + {6, 2, 7, 3}, + {1, 5, 0, 4}, + {7, 3, 6, 2}, +}; + +#define RB_SIZE 256 +#define RB_MASK (RB_SIZE - 1) + +#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx) +#define RB_FULL (RB_ENTRIES == RB_SIZE) +#define RB_EMPTY (!RB_ENTRIES) + +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) + +#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx) +#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= FIFO_SIZE) +#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx) + +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff + +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), + FIFO_WRITE_DWORD = (0x03 << 24) +}; + +typedef struct +{ + uint32_t addr_type; + uint32_t val; +} fifo_entry_t; + +typedef struct s3d_t +{ + uint32_t cmd_set; + int clip_l, clip_r, clip_t, clip_b; + + uint32_t dest_base; + uint32_t dest_str; + + uint32_t z_base; + uint32_t z_str; + + uint32_t tex_base; + uint32_t tex_bdr_clr; + uint32_t tbv, tbu; + int32_t TdVdX, TdUdX; + int32_t TdVdY, TdUdY; + uint32_t tus, tvs; + + int32_t TdZdX, TdZdY; + uint32_t tzs; + + int32_t TdWdX, TdWdY; + uint32_t tws; + + int32_t TdDdX, TdDdY; + uint32_t tds; + + int16_t TdGdX, TdBdX, TdRdX, TdAdX; + int16_t TdGdY, TdBdY, TdRdY, TdAdY; + uint32_t tgs, tbs, trs, tas; + + uint32_t TdXdY12; + uint32_t txend12; + uint32_t TdXdY01; + uint32_t txend01; + uint32_t TdXdY02; + uint32_t txs; + uint32_t tys; + int ty01, ty12, tlr; +} s3d_t; + +typedef struct virge_t +{ + mem_mapping_t linear_mapping; + mem_mapping_t mmio_mapping; + mem_mapping_t new_mmio_mapping; + + rom_t bios_rom; + + svga_t svga; + + uint8_t bank; + uint8_t ma_ext; + int width; + int bpp; + + uint8_t virge_id, virge_id_high, virge_id_low, virge_rev; + + uint32_t linear_base, linear_size; + + uint8_t pci_regs[256]; + int card; + + int is_375; + + int bilinear_enabled; + int dithering_enabled; + int memory_size; + + int pixel_count, tri_count; + + thread_t *render_thread; + event_t *wake_render_thread; + event_t *wake_main_thread; + event_t *not_full_event; + + uint32_t hwcursor_col[2]; + int hwcursor_col_pos; + + struct + { + uint32_t src_base; + uint32_t dest_base; + int clip_l, clip_r, clip_t, clip_b; + int dest_str, src_str; + uint32_t mono_pat_0; + uint32_t mono_pat_1; + uint32_t pat_bg_clr; + uint32_t pat_fg_clr; + uint32_t src_bg_clr; + uint32_t src_fg_clr; + uint32_t cmd_set; + int r_width, r_height; + int rsrc_x, rsrc_y; + int rdest_x, rdest_y; + + int lxend0, lxend1; + int32_t ldx; + uint32_t lxstart, lystart; + int lycnt; + int line_dir; + + int src_x, src_y; + int dest_x, dest_y; + int w, h; + uint8_t rop; + + int data_left_count; + uint32_t data_left; + + uint32_t pattern_8[8*8]; + uint32_t pattern_16[8*8]; + uint32_t pattern_32[8*8]; + + uint32_t prdx; + uint32_t prxstart; + uint32_t pldx; + uint32_t plxstart; + uint32_t pystart; + uint32_t pycnt; + uint32_t dest_l, dest_r; + } s3d; + + s3d_t s3d_tri; + + s3d_t s3d_buffer[RB_SIZE]; + int s3d_read_idx, s3d_write_idx; + int s3d_busy; + + struct + { + uint32_t pri_ctrl; + uint32_t chroma_ctrl; + uint32_t sec_ctrl; + uint32_t chroma_upper_bound; + uint32_t sec_filter; + uint32_t blend_ctrl; + uint32_t pri_fb0, pri_fb1; + uint32_t pri_stride; + uint32_t buffer_ctrl; + uint32_t sec_fb0, sec_fb1; + uint32_t sec_stride; + uint32_t overlay_ctrl; + int32_t k1_vert_scale; + int32_t k2_vert_scale; + int32_t dda_vert_accumulator; + int32_t k1_horiz_scale; + int32_t k2_horiz_scale; + int32_t dda_horiz_accumulator; + uint32_t fifo_ctrl; + uint32_t pri_start; + uint32_t pri_size; + uint32_t sec_start; + uint32_t sec_size; + + int sdif; + + int pri_x, pri_y, pri_w, pri_h; + int sec_x, sec_y, sec_w, sec_h; + } streams; + + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; + + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + + int virge_busy; + + uint8_t subsys_stat, subsys_cntl; +} virge_t; + +static __inline void wake_fifo_thread(virge_t *virge) +{ + thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + +static void queue_triangle(virge_t *virge); + +static void s3_virge_recalctimings(svga_t *svga); +static void s3_virge_updatemapping(virge_t *virge); + +static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); + +static uint8_t s3_virge_mmio_read(uint32_t addr, void *p); +static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p); +static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p); +static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p); +static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p); +static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p); + +enum +{ + CMD_SET_AE = 1, + CMD_SET_HC = (1 << 1), + + CMD_SET_FORMAT_MASK = (7 << 2), + CMD_SET_FORMAT_8 = (0 << 2), + CMD_SET_FORMAT_16 = (1 << 2), + CMD_SET_FORMAT_24 = (2 << 2), + + CMD_SET_MS = (1 << 6), + CMD_SET_IDS = (1 << 7), + CMD_SET_MP = (1 << 8), + CMD_SET_TP = (1 << 9), + + CMD_SET_ITA_MASK = (3 << 10), + CMD_SET_ITA_BYTE = (0 << 10), + CMD_SET_ITA_WORD = (1 << 10), + CMD_SET_ITA_DWORD = (2 << 10), + + CMD_SET_ZUP = (1 << 23), + + CMD_SET_ZB_MODE = (3 << 24), + + CMD_SET_XP = (1 << 25), + CMD_SET_YP = (1 << 26), + + CMD_SET_COMMAND_MASK = (15 << 27) +}; + +#define CMD_SET_ABC_SRC (1 << 18) +#define CMD_SET_ABC_ENABLE (1 << 19) +#define CMD_SET_TWE (1 << 26) + +enum +{ + CMD_SET_COMMAND_BITBLT = (0 << 27), + CMD_SET_COMMAND_RECTFILL = (2 << 27), + CMD_SET_COMMAND_LINE = (3 << 27), + CMD_SET_COMMAND_POLY = (5 << 27), + CMD_SET_COMMAND_NOP = (15 << 27) +}; + +#define INT_VSY (1 << 0) +#define INT_S3D_DONE (1 << 1) +#define INT_FIFO_OVF (1 << 2) +#define INT_FIFO_EMP (1 << 3) +#define INT_3DF_EMP (1 << 6) +#define INT_MASK 0xff + +static void s3_virge_update_irqs(virge_t *virge) +{ + if (!PCI) + { + return; + } + + if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK)) + pci_set_irq(virge->card, PCI_INTA); + else + pci_clear_irq(virge->card, PCI_INTA); +} + +static void s3_virge_out(uint16_t addr, uint8_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + svga_t *svga = &virge->svga; + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3c5: + if (svga->seqaddr >= 0x10) + { + svga->seqregs[svga->seqaddr & 0x1f]=val; + svga_recalctimings(svga); + return; + } + if (svga->seqaddr == 4) /*Chain-4 - update banking*/ + { + if (val & 8) svga->write_bank = svga->read_bank = virge->bank << 16; + else svga->write_bank = svga->read_bank = virge->bank << 14; + } + break; + + case 0x3d4: + svga->crtcreg = val; + return; + case 0x3d5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) + return; + if (svga->crtcreg >= 0x80) + return; + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + switch (svga->crtcreg) + { + case 0x31: + virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4); + break; + case 0x32: + if ((svga->crtc[0x67] & 0xc) != 0xc) + svga->vrammask = (val & 0x40) ? 0x3ffff : ((virge->memory_size << 20) - 1); + s3_virge_update_irqs(virge); + break; + + case 0x50: + switch (svga->crtc[0x50] & 0xc1) + { + case 0x00: virge->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break; + case 0x01: virge->width = 1152; break; + case 0x40: virge->width = 640; break; + case 0x80: virge->width = 800; break; + case 0x81: virge->width = 1600; break; + case 0xc0: virge->width = 1280; break; + } + virge->bpp = (svga->crtc[0x50] >> 4) & 3; + break; + case 0x69: + virge->ma_ext = val & 0x1f; + break; + + case 0x35: + virge->bank = (virge->bank & 0x70) | (val & 0xf); + if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; + else svga->write_bank = svga->read_bank = virge->bank << 14; + break; + case 0x51: + virge->bank = (virge->bank & 0x4f) | ((val & 0xc) << 2); + if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; + else svga->write_bank = svga->read_bank = virge->bank << 14; + virge->ma_ext = (virge->ma_ext & ~0xc) | ((val & 3) << 2); + break; + case 0x6a: + virge->bank = val; + if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; + else svga->write_bank = svga->read_bank = virge->bank << 14; + break; + + case 0x3a: + if (val & 0x10) svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ + break; + + case 0x45: + svga->hwcursor.ena = val & 1; + break; + case 0x46: case 0x47: case 0x48: case 0x49: + case 0x4c: case 0x4d: case 0x4e: case 0x4f: + svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; + svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; + svga->hwcursor.xoff = svga->crtc[0x4e] & 63; + svga->hwcursor.yoff = svga->crtc[0x4f] & 63; + svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); + break; + + case 0x4a: + virge->hwcursor_col[1] = (virge->hwcursor_col[1] & ~(0xff << (virge->hwcursor_col_pos * 8))) | + (val << (virge->hwcursor_col_pos * 8)); + virge->hwcursor_col_pos++; + virge->hwcursor_col_pos &= 3; + break; + case 0x4b: + virge->hwcursor_col[0] = (virge->hwcursor_col[0] & ~(0xff << (virge->hwcursor_col_pos * 8))) | + (val << (virge->hwcursor_col_pos * 8)); + virge->hwcursor_col_pos++; + virge->hwcursor_col_pos &= 3; + break; + + case 0x53: + case 0x58: case 0x59: case 0x5a: + s3_virge_updatemapping(virge); + break; + + case 0x67: + switch (val >> 4) + { + case 2: case 3: svga->bpp = 15; break; + case 4: case 5: svga->bpp = 16; break; + case 7: svga->bpp = 24; break; + case 13: svga->bpp = (gfxcard == GFX_VIRGEVX) ? 24 : 32; break; + default: svga->bpp = 8; break; + } + break; + } + if (old != val) + { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + } + svga_out(addr, val, svga); +} + +static uint8_t s3_virge_in(uint16_t addr, void *p) +{ + virge_t *virge = (virge_t *)p; + svga_t *svga = &virge->svga; + uint8_t ret; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3c1: + if (svga->attraddr > 0x14) + ret = 0xff; + else + ret = svga_in(addr, svga); + break; + + case 0x3c5: + if (svga->seqaddr >= 8) + ret = svga->seqregs[svga->seqaddr & 0x1f]; + else if (svga->seqaddr <= 4) + ret = svga_in(addr, svga); + else + ret = 0xff; + break; + + case 0x3D4: + ret = svga->crtcreg; + break; + case 0x3D5: + switch (svga->crtcreg) + { + case 0x2d: ret = virge->virge_id_high; break; /*Extended chip ID*/ + case 0x2e: ret = virge->virge_id_low; break; /*New chip ID*/ + case 0x2f: ret = virge->virge_rev; break; + case 0x30: ret = virge->virge_id; break; /*Chip ID*/ + case 0x31: ret = (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); break; + case 0x35: ret = (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); break; + case 0x36: ret = (svga->crtc[0x36] & 0xfc) | 2; break; /*PCI bus*/ + case 0x45: virge->hwcursor_col_pos = 0; ret = svga->crtc[0x45]; break; + case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); break; + case 0x69: ret = virge->ma_ext; break; + case 0x6a: ret = virge->bank; break; + default: ret = svga->crtc[svga->crtcreg]; break; + } + break; + + default: + ret = svga_in(addr, svga); + break; + } + return ret; +} + +static void s3_virge_recalctimings(svga_t *svga) +{ + virge_t *virge = (virge_t *)svga->p; + + if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; + if (svga->crtc[0x5d] & 0x02) svga->hdisp += 0x100; + if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; + if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; + if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400; + if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; + if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; + svga->interlace = svga->crtc[0x42] & 0x20; + + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ + { + svga->ma_latch |= (virge->ma_ext << 16); + if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; + else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; + if (!svga->rowoffset) svga->rowoffset = 256; + + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) + { + switch (svga->bpp) + { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + break; + case 16: + svga->render = svga_render_16bpp_highres; + break; + case 24: + svga->render = svga_render_24bpp_highres; + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; + } + } + + if (gfxcard != GFX_VIRGEVX) + { + if ((svga->bpp == 15) || (svga->bpp == 16)) + { + svga->htotal >>= 1; + svga->hdisp >>= 1; + } + if (svga->bpp == 24) + { + svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ + } + } + svga->vrammask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : ((virge->memory_size << 20) - 1); + } + else /*Streams mode*/ + { + if (virge->streams.buffer_ctrl & 1) + svga->ma_latch = virge->streams.pri_fb1 >> 2; + else + svga->ma_latch = virge->streams.pri_fb0 >> 2; + + svga->hdisp = virge->streams.pri_w + 1; + if (virge->streams.pri_h < svga->dispend) + svga->dispend = virge->streams.pri_h; + + svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; + svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; + svga->overlay.ysize = virge->streams.sec_h; + + if (virge->streams.buffer_ctrl & 2) + svga->overlay.addr = virge->streams.sec_fb1; + else + svga->overlay.addr = virge->streams.sec_fb0; + + svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.v_acc = virge->streams.dda_vert_accumulator; + svga->rowoffset = virge->streams.pri_stride >> 3; + + switch ((virge->streams.pri_ctrl >> 24) & 0x7) + { + case 0: /*RGB-8 (CLUT)*/ + svga->render = svga_render_8bpp_highres; + break; + case 3: /*KRGB-16 (1.5.5.5)*/ + svga->htotal >>= 1; + svga->render = svga_render_15bpp_highres; + break; + case 5: /*RGB-16 (5.6.5)*/ + svga->htotal >>= 1; + svga->render = svga_render_16bpp_highres; + break; + case 6: /*RGB-24 (8.8.8)*/ + svga->render = svga_render_24bpp_highres; + break; + case 7: /*XRGB-32 (X.8.8.8)*/ + svga->render = svga_render_32bpp_highres; + break; + } + svga->vrammask = (virge->memory_size << 20) - 1; + } + + if (((svga->miscout >> 2) & 3) == 3) + { + int n = svga->seqregs[0x12] & 0x1f; + int r = (svga->seqregs[0x12] >> 5) & ((virge->is_375 || (gfxcard == GFX_VIRGEVX)) ? 7 : 3); + int m = svga->seqregs[0x13] & 0x7f; + double freq = (((double)m + 2) / (((double)n + 2) * (double)(1 << r))) * 14318184.0; + + svga->clock = cpuclock / freq; + } +} + +static void s3_virge_updatemapping(virge_t *virge) +{ + svga_t *svga = &virge->svga; + + if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&virge->linear_mapping); + mem_mapping_disable(&virge->mmio_mapping); + mem_mapping_disable(&virge->new_mmio_mapping); + return; + } + + //pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); + switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + + virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + + //pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); + if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ + { + switch (svga->crtc[0x58] & 3) + { + case 0: /*64k*/ + virge->linear_size = 0x10000; + break; + case 1: /*1mb*/ + virge->linear_size = 0x100000; + break; + case 2: /*2mb*/ + virge->linear_size = 0x200000; + break; + case 3: /*8mb*/ + virge->linear_size = 0x400000; + break; + } + virge->linear_base &= ~(virge->linear_size - 1); + svga->linear_base = virge->linear_base; + //pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); + if (virge->linear_base == 0xa0000) + { + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_disable(&virge->linear_mapping); + } + else + mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); + svga->fb_only = 1; + } + else + { + mem_mapping_disable(&virge->linear_mapping); + svga->fb_only = 0; + } + + //pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); + if (svga->crtc[0x53] & 0x10) /*Old MMIO*/ + { + if (svga->crtc[0x53] & 0x20) + mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); + else + mem_mapping_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000); + } + else + mem_mapping_disable(&virge->mmio_mapping); + + if (svga->crtc[0x53] & 0x08) /*New MMIO*/ + mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); + else + mem_mapping_disable(&virge->new_mmio_mapping); + +} + +static void s3_virge_vblank_start(svga_t *svga) +{ + virge_t *virge = (virge_t *)svga->p; + + virge->subsys_stat |= INT_VSY; + s3_virge_update_irqs(virge); +} + +static void s3_virge_wait_fifo_idle(virge_t *virge) +{ + while (!FIFO_EMPTY) + { + wake_fifo_thread(virge); + thread_wait_event(virge->fifo_not_full_event, 1); + } +} + +static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) +{ + virge_t *virge = (virge_t *)p; + uint8_t ret; + + reg_reads++; + switch (addr & 0xffff) + { + case 0x8505: + if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) + ret = 0x10; + else + ret = 0x10 | (1 << 5); + if (!virge->virge_busy) + wake_fifo_thread(virge); + return ret; + + case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: + case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: + case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: + case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: + case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: + case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: + case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: + case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: + case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: + case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: + case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: + case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: + return s3_virge_in(addr & 0x3ff, p); + } + return 0xff; +} +static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p) +{ + reg_reads++; + switch (addr & 0xfffe) + { + default: + return s3_virge_mmio_read(addr, p) | (s3_virge_mmio_read(addr + 1, p) << 8); + } + return 0xffff; +} +static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) +{ + virge_t *virge = (virge_t *)p; + uint32_t ret = 0xffffffff; + reg_reads++; + switch (addr & 0xfffc) + { + case 0x8180: + ret = virge->streams.pri_ctrl; + break; + case 0x8184: + ret = virge->streams.chroma_ctrl; + break; + case 0x8190: + ret = virge->streams.sec_ctrl; + break; + case 0x8194: + ret = virge->streams.chroma_upper_bound; + break; + case 0x8198: + ret = virge->streams.sec_filter; + break; + case 0x81a0: + ret = virge->streams.blend_ctrl; + break; + case 0x81c0: + ret = virge->streams.pri_fb0; + break; + case 0x81c4: + ret = virge->streams.pri_fb1; + break; + case 0x81c8: + ret = virge->streams.pri_stride; + break; + case 0x81cc: + ret = virge->streams.buffer_ctrl; + break; + case 0x81d0: + ret = virge->streams.sec_fb0; + break; + case 0x81d4: + ret = virge->streams.sec_fb1; + break; + case 0x81d8: + ret = virge->streams.sec_stride; + break; + case 0x81dc: + ret = virge->streams.overlay_ctrl; + break; + case 0x81e0: + ret = virge->streams.k1_vert_scale; + break; + case 0x81e4: + ret = virge->streams.k2_vert_scale; + break; + case 0x81e8: + ret = virge->streams.dda_vert_accumulator; + break; + case 0x81ec: + ret = virge->streams.fifo_ctrl; + break; + case 0x81f0: + ret = virge->streams.pri_start; + break; + case 0x81f4: + ret = virge->streams.pri_size; + break; + case 0x81f8: + ret = virge->streams.sec_start; + break; + case 0x81fc: + ret = virge->streams.sec_size; + break; + + case 0x8504: + if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) + ret = (0x10 << 8); + else + ret = (0x10 << 8) | (1 << 13); + ret |= virge->subsys_stat; + if (!virge->virge_busy) + wake_fifo_thread(virge); + break; + case 0xa4d4: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.src_base; + break; + case 0xa4d8: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.dest_base; + break; + case 0xa4dc: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; + break; + case 0xa4e0: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; + break; + case 0xa4e4: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; + break; + case 0xa4e8: case 0xace8: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.mono_pat_0; + break; + case 0xa4ec: case 0xacec: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.mono_pat_1; + break; + case 0xa4f0: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.pat_bg_clr; + break; + case 0xa4f4: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.pat_fg_clr; + break; + case 0xa4f8: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.src_bg_clr; + break; + case 0xa4fc: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.src_fg_clr; + break; + case 0xa500: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.cmd_set; + break; + case 0xa504: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; + break; + case 0xa508: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; + break; + case 0xa50c: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; + break; + + default: + ret = s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16); + } + return ret; +} + +static void fifo_thread(void *param) +{ + virge_t *virge = (virge_t *)param; + + while (1) + { + thread_set_event(virge->fifo_not_full_event); + thread_wait_event(virge->wake_fifo_thread, -1); + thread_reset_event(virge->wake_fifo_thread); + virge->virge_busy = 1; + while (!FIFO_EMPTY) + { + uint64_t start_time = timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK]; + uint32_t val = fifo->val; + + switch (fifo->addr_type & FIFO_TYPE) + { + case FIFO_WRITE_BYTE: + if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) + s3_virge_bitblt(virge, 8, val); + break; + case FIFO_WRITE_WORD: + if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); + else + s3_virge_bitblt(virge, 16, val); + } + break; + case FIFO_WRITE_DWORD: + if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); + } + else + { + switch ((fifo->addr_type & FIFO_ADDR) & 0xfffc) + { + case 0xa000: case 0xa004: case 0xa008: case 0xa00c: + case 0xa010: case 0xa014: case 0xa018: case 0xa01c: + case 0xa020: case 0xa024: case 0xa028: case 0xa02c: + case 0xa030: case 0xa034: case 0xa038: case 0xa03c: + case 0xa040: case 0xa044: case 0xa048: case 0xa04c: + case 0xa050: case 0xa054: case 0xa058: case 0xa05c: + case 0xa060: case 0xa064: case 0xa068: case 0xa06c: + case 0xa070: case 0xa074: case 0xa078: case 0xa07c: + case 0xa080: case 0xa084: case 0xa088: case 0xa08c: + case 0xa090: case 0xa094: case 0xa098: case 0xa09c: + case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: + case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: + case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: + case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: + case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: + case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: + case 0xa100: case 0xa104: case 0xa108: case 0xa10c: + case 0xa110: case 0xa114: case 0xa118: case 0xa11c: + case 0xa120: case 0xa124: case 0xa128: case 0xa12c: + case 0xa130: case 0xa134: case 0xa138: case 0xa13c: + case 0xa140: case 0xa144: case 0xa148: case 0xa14c: + case 0xa150: case 0xa154: case 0xa158: case 0xa15c: + case 0xa160: case 0xa164: case 0xa168: case 0xa16c: + case 0xa170: case 0xa174: case 0xa178: case 0xa17c: + case 0xa180: case 0xa184: case 0xa188: case 0xa18c: + case 0xa190: case 0xa194: case 0xa198: case 0xa19c: + case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: + case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: + case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: + case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: + case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: + case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: + { + int x = (fifo->addr_type & FIFO_ADDR) & 4; + int y = ((fifo->addr_type & FIFO_ADDR) >> 3) & 7; + virge->s3d.pattern_8[y*8 + x] = val & 0xff; + virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; + virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; + virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; + + x = ((fifo->addr_type & FIFO_ADDR) >> 1) & 6; + y = ((fifo->addr_type & FIFO_ADDR) >> 4) & 7; + virge->s3d.pattern_16[y*8 + x] = val & 0xffff; + virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; + + x = ((fifo->addr_type & FIFO_ADDR) >> 2) & 7; + y = ((fifo->addr_type & FIFO_ADDR) >> 5) & 7; + virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; + } + break; + + case 0xa4d4: case 0xa8d4: + virge->s3d.src_base = val & 0x3ffff8; + break; + case 0xa4d8: case 0xa8d8: + virge->s3d.dest_base = val & 0x3ffff8; + break; + case 0xa4dc: case 0xa8dc: + virge->s3d.clip_l = (val >> 16) & 0x7ff; + virge->s3d.clip_r = val & 0x7ff; + break; + case 0xa4e0: case 0xa8e0: + virge->s3d.clip_t = (val >> 16) & 0x7ff; + virge->s3d.clip_b = val & 0x7ff; + break; + case 0xa4e4: case 0xa8e4: + virge->s3d.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xa4e8: case 0xace8: + virge->s3d.mono_pat_0 = val; + break; + case 0xa4ec: case 0xacec: + virge->s3d.mono_pat_1 = val; + break; + case 0xa4f0: case 0xacf0: + virge->s3d.pat_bg_clr = val; + break; + case 0xa4f4: case 0xa8f4: case 0xacf4: + virge->s3d.pat_fg_clr = val; + break; + case 0xa4f8: + virge->s3d.src_bg_clr = val; + break; + case 0xa4fc: + virge->s3d.src_fg_clr = val; + break; + case 0xa500: case 0xa900: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa504: + virge->s3d.r_width = (val >> 16) & 0x7ff; + virge->s3d.r_height = val & 0x7ff; + break; + case 0xa508: + virge->s3d.rsrc_x = (val >> 16) & 0x7ff; + virge->s3d.rsrc_y = val & 0x7ff; + break; + case 0xa50c: + virge->s3d.rdest_x = (val >> 16) & 0x7ff; + virge->s3d.rdest_y = val & 0x7ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa96c: + virge->s3d.lxend0 = (val >> 16) & 0x7ff; + virge->s3d.lxend1 = val & 0x7ff; + break; + case 0xa970: + virge->s3d.ldx = (int32_t)val; + break; + case 0xa974: + virge->s3d.lxstart = val; + break; + case 0xa978: + virge->s3d.lystart = val & 0x7ff; + break; + case 0xa97c: + virge->s3d.lycnt = val & 0x7ff; + virge->s3d.line_dir = val >> 31; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xad00: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xad68: + virge->s3d.prdx = val; + break; + case 0xad6c: + virge->s3d.prxstart = val; + break; + case 0xad70: + virge->s3d.pldx = val; + break; + case 0xad74: + virge->s3d.plxstart = val; + break; + case 0xad78: + virge->s3d.pystart = val & 0x7ff; + break; + case 0xad7c: + virge->s3d.pycnt = val & 0x300007ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xb4d4: + virge->s3d_tri.z_base = val & 0x3ffff8; + break; + case 0xb4d8: + virge->s3d_tri.dest_base = val & 0x3ffff8; + break; + case 0xb4dc: + virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_r = val & 0x7ff; + break; + case 0xb4e0: + virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_b = val & 0x7ff; + break; + case 0xb4e4: + virge->s3d_tri.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xb4e8: + virge->s3d_tri.z_str = val & 0xff8; + break; + case 0xb4ec: + virge->s3d_tri.tex_base = val & 0x3ffff8; + break; + case 0xb4f0: + virge->s3d_tri.tex_bdr_clr = val & 0xffffff; + break; + case 0xb500: + virge->s3d_tri.cmd_set = val; + if (!(val & CMD_SET_AE)) + queue_triangle(virge); + break; + case 0xb504: + virge->s3d_tri.tbv = val & 0xfffff; + break; + case 0xb508: + virge->s3d_tri.tbu = val & 0xfffff; + break; + case 0xb50c: + virge->s3d_tri.TdWdX = val; + break; + case 0xb510: + virge->s3d_tri.TdWdY = val; + break; + case 0xb514: + virge->s3d_tri.tws = val; + break; + case 0xb518: + virge->s3d_tri.TdDdX = val; + break; + case 0xb51c: + virge->s3d_tri.TdVdX = val; + break; + case 0xb520: + virge->s3d_tri.TdUdX = val; + break; + case 0xb524: + virge->s3d_tri.TdDdY = val; + break; + case 0xb528: + virge->s3d_tri.TdVdY = val; + break; + case 0xb52c: + virge->s3d_tri.TdUdY = val; + break; + case 0xb530: + virge->s3d_tri.tds = val; + break; + case 0xb534: + virge->s3d_tri.tvs = val; + break; + case 0xb538: + virge->s3d_tri.tus = val; + break; + case 0xb53c: + virge->s3d_tri.TdGdX = val >> 16; + virge->s3d_tri.TdBdX = val & 0xffff; + break; + case 0xb540: + virge->s3d_tri.TdAdX = val >> 16; + virge->s3d_tri.TdRdX = val & 0xffff; + break; + case 0xb544: + virge->s3d_tri.TdGdY = val >> 16; + virge->s3d_tri.TdBdY = val & 0xffff; + break; + case 0xb548: + virge->s3d_tri.TdAdY = val >> 16; + virge->s3d_tri.TdRdY = val & 0xffff; + break; + case 0xb54c: + virge->s3d_tri.tgs = (val >> 16) & 0xffff; + virge->s3d_tri.tbs = val & 0xffff; + break; + case 0xb550: + virge->s3d_tri.tas = (val >> 16) & 0xffff; + virge->s3d_tri.trs = val & 0xffff; + break; + + case 0xb554: + virge->s3d_tri.TdZdX = val; + break; + case 0xb558: + virge->s3d_tri.TdZdY = val; + break; + case 0xb55c: + virge->s3d_tri.tzs = val; + break; + case 0xb560: + virge->s3d_tri.TdXdY12 = val; + break; + case 0xb564: + virge->s3d_tri.txend12 = val; + break; + case 0xb568: + virge->s3d_tri.TdXdY01 = val; + break; + case 0xb56c: + virge->s3d_tri.txend01 = val; + break; + case 0xb570: + virge->s3d_tri.TdXdY02 = val; + break; + case 0xb574: + virge->s3d_tri.txs = val; + break; + case 0xb578: + virge->s3d_tri.tys = val; + break; + case 0xb57c: + virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; + virge->s3d_tri.ty12 = val & 0x7ff; + virge->s3d_tri.tlr = val >> 31; + if (virge->s3d_tri.cmd_set & CMD_SET_AE) + queue_triangle(virge); + break; + } + } + break; + } + + virge->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; + + if (FIFO_ENTRIES > 0xe000) + thread_set_event(virge->fifo_not_full_event); + + end_time = timer_read(); + virge_time += end_time - start_time; + } + virge->virge_busy = 0; + } +} + +static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) +{ + fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; + + if (FIFO_FULL) + { + thread_reset_event(virge->fifo_not_full_event); + if (FIFO_FULL) + { + thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } + + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; + + virge->fifo_write_idx++; + + /* if (FIFO_ENTRIES > 0xe000) + wake_fifo_thread(virge); */ + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(virge); +} + +static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + + reg_writes++; + if ((addr & 0xfffc) < 0x8000) + { + s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE); + } + else switch (addr & 0xffff) + { + case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: + case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: + case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: + case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: + case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: + case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: + case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: + case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: + case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: + case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: + case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: + case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: + s3_virge_out(addr & 0x3ff, val, p); + break; + } + + +} +static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + reg_writes++; + if ((addr & 0xfffc) < 0x8000) + { + s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD); + } + else switch (addr & 0xfffe) + { + case 0x83d4: + s3_virge_mmio_write(addr, val, p); + s3_virge_mmio_write(addr + 1, val >> 8, p); + break; + } +} +static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + svga_t *svga = &virge->svga; + reg_writes++; + + pclog("Write Address %x\n", addr & 0xe000); + + if ((addr & 0xfffc) < 0x8000) + { + s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); + } + else switch (addr & 0xfffc) + { + case 0: + s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + + case 0x8180: + virge->streams.pri_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x8184: + virge->streams.chroma_ctrl = val; + break; + case 0x8190: + virge->streams.sec_ctrl = val; + virge->streams.dda_horiz_accumulator = val & 0xfff; + if (val & (1 << 11)) + virge->streams.dda_horiz_accumulator |= 0xfffff800; + virge->streams.sdif = (val >> 24) & 7; + break; + case 0x8194: + virge->streams.chroma_upper_bound = val; + break; + case 0x8198: + virge->streams.sec_filter = val; + virge->streams.k1_horiz_scale = val & 0x7ff; + if (val & (1 << 10)) + virge->streams.k1_horiz_scale |= 0xfffff800; + virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff; + if ((val >> 16) & (1 << 10)) + virge->streams.k2_horiz_scale |= 0xfffff800; + break; + case 0x81a0: + virge->streams.blend_ctrl = val; + break; + case 0x81c0: + virge->streams.pri_fb0 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81c4: + virge->streams.pri_fb1 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81c8: + virge->streams.pri_stride = val & 0xfff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81cc: + virge->streams.buffer_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81d0: + virge->streams.sec_fb0 = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81d4: + virge->streams.sec_fb1 = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81d8: + virge->streams.sec_stride = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81dc: + virge->streams.overlay_ctrl = val; + break; + case 0x81e0: + virge->streams.k1_vert_scale = val & 0x7ff; + if (val & (1 << 10)) + virge->streams.k1_vert_scale |= 0xfffff800; + break; + case 0x81e4: + virge->streams.k2_vert_scale = val & 0x7ff; + if (val & (1 << 10)) + virge->streams.k2_vert_scale |= 0xfffff800; + break; + case 0x81e8: + virge->streams.dda_vert_accumulator = val & 0xfff; + if (val & (1 << 11)) + virge->streams.dda_vert_accumulator |= 0xfffff800; + break; + case 0x81ec: + virge->streams.fifo_ctrl = val; + break; + case 0x81f0: + virge->streams.pri_start = val; + virge->streams.pri_x = (val >> 16) & 0x7ff; + virge->streams.pri_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81f4: + virge->streams.pri_size = val; + virge->streams.pri_w = (val >> 16) & 0x7ff; + virge->streams.pri_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81f8: + virge->streams.sec_start = val; + virge->streams.sec_x = (val >> 16) & 0x7ff; + virge->streams.sec_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81fc: + virge->streams.sec_size = val; + virge->streams.sec_w = (val >> 16) & 0x7ff; + virge->streams.sec_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + + case 0x8504: + virge->subsys_stat &= ~(val & 0xff); + virge->subsys_cntl = (val >> 8); + s3_virge_update_irqs(virge); + break; + + case 0xa000: case 0xa004: case 0xa008: case 0xa00c: + case 0xa010: case 0xa014: case 0xa018: case 0xa01c: + case 0xa020: case 0xa024: case 0xa028: case 0xa02c: + case 0xa030: case 0xa034: case 0xa038: case 0xa03c: + case 0xa040: case 0xa044: case 0xa048: case 0xa04c: + case 0xa050: case 0xa054: case 0xa058: case 0xa05c: + case 0xa060: case 0xa064: case 0xa068: case 0xa06c: + case 0xa070: case 0xa074: case 0xa078: case 0xa07c: + case 0xa080: case 0xa084: case 0xa088: case 0xa08c: + case 0xa090: case 0xa094: case 0xa098: case 0xa09c: + case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: + case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: + case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: + case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: + case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: + case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: + case 0xa100: case 0xa104: case 0xa108: case 0xa10c: + case 0xa110: case 0xa114: case 0xa118: case 0xa11c: + case 0xa120: case 0xa124: case 0xa128: case 0xa12c: + case 0xa130: case 0xa134: case 0xa138: case 0xa13c: + case 0xa140: case 0xa144: case 0xa148: case 0xa14c: + case 0xa150: case 0xa154: case 0xa158: case 0xa15c: + case 0xa160: case 0xa164: case 0xa168: case 0xa16c: + case 0xa170: case 0xa174: case 0xa178: case 0xa17c: + case 0xa180: case 0xa184: case 0xa188: case 0xa18c: + case 0xa190: case 0xa194: case 0xa198: case 0xa19c: + case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: + case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: + case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: + case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: + case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: + case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: + { + int x = addr & 4; + int y = (addr >> 3) & 7; + virge->s3d.pattern_8[y*8 + x] = val & 0xff; + virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; + virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; + virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; + + x = (addr >> 1) & 6; + y = (addr >> 4) & 7; + virge->s3d.pattern_16[y*8 + x] = val & 0xffff; + virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; + + x = (addr >> 2) & 7; + y = (addr >> 5) & 7; + virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; + } + break; + + case 0xa4d4: case 0xa8d4: + virge->s3d.src_base = val & 0x3ffff8; + break; + case 0xa4d8: case 0xa8d8: + virge->s3d.dest_base = val & 0x3ffff8; + break; + case 0xa4dc: case 0xa8dc: + virge->s3d.clip_l = (val >> 16) & 0x7ff; + virge->s3d.clip_r = val & 0x7ff; + break; + case 0xa4e0: case 0xa8e0: + virge->s3d.clip_t = (val >> 16) & 0x7ff; + virge->s3d.clip_b = val & 0x7ff; + break; + case 0xa4e4: case 0xa8e4: + virge->s3d.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xa4e8: case 0xace8: + virge->s3d.mono_pat_0 = val; + break; + case 0xa4ec: case 0xacec: + virge->s3d.mono_pat_1 = val; + break; + case 0xa4f0: case 0xacf0: + virge->s3d.pat_bg_clr = val; + break; + case 0xa4f4: case 0xa8f4: case 0xacf4: + virge->s3d.pat_fg_clr = val; + break; + case 0xa4f8: + virge->s3d.src_bg_clr = val; + break; + case 0xa4fc: + virge->s3d.src_fg_clr = val; + break; + case 0xa500: case 0xa900: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa504: + virge->s3d.r_width = (val >> 16) & 0x7ff; + virge->s3d.r_height = val & 0x7ff; + break; + case 0xa508: + virge->s3d.rsrc_x = (val >> 16) & 0x7ff; + virge->s3d.rsrc_y = val & 0x7ff; + break; + case 0xa50c: + virge->s3d.rdest_x = (val >> 16) & 0x7ff; + virge->s3d.rdest_y = val & 0x7ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa96c: + virge->s3d.lxend0 = (val >> 16) & 0x7ff; + virge->s3d.lxend1 = val & 0x7ff; + break; + case 0xa970: + virge->s3d.ldx = (int32_t)val; + break; + case 0xa974: + virge->s3d.lxstart = val; + break; + case 0xa978: + virge->s3d.lystart = val & 0x7ff; + break; + case 0xa97c: + virge->s3d.lycnt = val & 0x7ff; + virge->s3d.line_dir = val >> 31; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xad00: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xad68: + virge->s3d.prdx = val; + break; + case 0xad6c: + virge->s3d.prxstart = val; + break; + case 0xad70: + virge->s3d.pldx = val; + break; + case 0xad74: + virge->s3d.plxstart = val; + break; + case 0xad78: + virge->s3d.pystart = val & 0x7ff; + break; + case 0xad7c: + virge->s3d.pycnt = val & 0x300007ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xb4d4: + virge->s3d_tri.z_base = val & 0x3ffff8; + break; + case 0xb4d8: + virge->s3d_tri.dest_base = val & 0x3ffff8; + break; + case 0xb4dc: + virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_r = val & 0x7ff; + break; + case 0xb4e0: + virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_b = val & 0x7ff; + break; + case 0xb4e4: + virge->s3d_tri.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xb4e8: + virge->s3d_tri.z_str = val & 0xff8; + break; + case 0xb4ec: + virge->s3d_tri.tex_base = val & 0x3ffff8; + break; + case 0xb4f0: + virge->s3d_tri.tex_bdr_clr = val & 0xffffff; + break; + case 0xb500: + virge->s3d_tri.cmd_set = val; + if (!(val & CMD_SET_AE)) + queue_triangle(virge); + break; + case 0xb504: + virge->s3d_tri.tbv = val & 0xfffff; + break; + case 0xb508: + virge->s3d_tri.tbu = val & 0xfffff; + break; + case 0xb50c: + virge->s3d_tri.TdWdX = val; + break; + case 0xb510: + virge->s3d_tri.TdWdY = val; + break; + case 0xb514: + virge->s3d_tri.tws = val; + break; + case 0xb518: + virge->s3d_tri.TdDdX = val; + break; + case 0xb51c: + virge->s3d_tri.TdVdX = val; + break; + case 0xb520: + virge->s3d_tri.TdUdX = val; + break; + case 0xb524: + virge->s3d_tri.TdDdY = val; + break; + case 0xb528: + virge->s3d_tri.TdVdY = val; + break; + case 0xb52c: + virge->s3d_tri.TdUdY = val; + break; + case 0xb530: + virge->s3d_tri.tds = val; + break; + case 0xb534: + virge->s3d_tri.tvs = val; + break; + case 0xb538: + virge->s3d_tri.tus = val; + break; + case 0xb53c: + virge->s3d_tri.TdGdX = val >> 16; + virge->s3d_tri.TdBdX = val & 0xffff; + break; + case 0xb540: + virge->s3d_tri.TdAdX = val >> 16; + virge->s3d_tri.TdRdX = val & 0xffff; + break; + case 0xb544: + virge->s3d_tri.TdGdY = val >> 16; + virge->s3d_tri.TdBdY = val & 0xffff; + break; + case 0xb548: + virge->s3d_tri.TdAdY = val >> 16; + virge->s3d_tri.TdRdY = val & 0xffff; + break; + case 0xb54c: + virge->s3d_tri.tgs = (val >> 16) & 0xffff; + virge->s3d_tri.tbs = val & 0xffff; + break; + case 0xb550: + virge->s3d_tri.tas = (val >> 16) & 0xffff; + virge->s3d_tri.trs = val & 0xffff; + break; + + case 0xb554: + virge->s3d_tri.TdZdX = val; + break; + case 0xb558: + virge->s3d_tri.TdZdY = val; + break; + case 0xb55c: + virge->s3d_tri.tzs = val; + break; + case 0xb560: + virge->s3d_tri.TdXdY12 = val; + break; + case 0xb564: + virge->s3d_tri.txend12 = val; + break; + case 0xb568: + virge->s3d_tri.TdXdY01 = val; + break; + case 0xb56c: + virge->s3d_tri.txend01 = val; + break; + case 0xb570: + virge->s3d_tri.TdXdY02 = val; + break; + case 0xb574: + virge->s3d_tri.txs = val; + break; + case 0xb578: + virge->s3d_tri.tys = val; + break; + case 0xb57c: + virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; + virge->s3d_tri.ty12 = val & 0x7ff; + virge->s3d_tri.tlr = val >> 31; + if (virge->s3d_tri.cmd_set & CMD_SET_AE) + queue_triangle(virge); + break; + } +} + +#define READ(addr, val) \ + do \ + { \ + switch (bpp) \ + { \ + case 0: /*8 bpp*/ \ + val = vram[addr & 0x3fffff]; \ + break; \ + case 1: /*16 bpp*/ \ + val = *(uint16_t *)&vram[addr & 0x3fffff]; \ + break; \ + case 2: /*24 bpp*/ \ + val = (*(uint32_t *)&vram[addr & 0x3fffff]) & 0xffffff; \ + break; \ + } \ + } while (0) + +#define Z_READ(addr) *(uint16_t *)&vram[addr & 0x3fffff] + +#define Z_WRITE(addr, val) if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) *(uint16_t *)&vram[addr & 0x3fffff] = val + +#define CLIP(x, y) \ + do \ + { \ + if ((virge->s3d.cmd_set & CMD_SET_HC) && \ + (x < virge->s3d.clip_l || \ + x > virge->s3d.clip_r || \ + y < virge->s3d.clip_t || \ + y > virge->s3d.clip_b)) \ + update = 0; \ + } while (0) + +#define CLIP_3D(x, y) \ + do \ + { \ + if ((s3d_tri->cmd_set & CMD_SET_HC) && \ + (x < s3d_tri->clip_l || \ + x > s3d_tri->clip_r || \ + y < s3d_tri->clip_t || \ + y > s3d_tri->clip_b)) \ + update = 0; \ + } while (0) + +#define Z_CLIP(Zzb, Zs) \ + do \ + { \ + if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ + switch ((s3d_tri->cmd_set >> 20) & 7) \ + { \ + case 0: update = 0; break; \ + case 1: if (Zs <= Zzb) update = 0; else Zzb = Zs; break; \ + case 2: if (Zs != Zzb) update = 0; else Zzb = Zs; break; \ + case 3: if (Zs < Zzb) update = 0; else Zzb = Zs; break; \ + case 4: if (Zs >= Zzb) update = 0; else Zzb = Zs; break; \ + case 5: if (Zs == Zzb) update = 0; else Zzb = Zs; break; \ + case 6: if (Zs > Zzb) update = 0; else Zzb = Zs; break; \ + case 7: update = 1; Zzb = Zs; break; \ + } \ + } while (0) + +#define MIX() \ + do \ + { \ + int c; \ + for (c = 0; c < 24; c++) \ + { \ + int d = (dest & (1 << c)) ? 1 : 0; \ + if (source & (1 << c)) d |= 2; \ + if (pattern & (1 << c)) d |= 4; \ + if (virge->s3d.rop & (1 << d)) out |= (1 << c); \ + } \ + } while (0) + +#define WRITE(addr, val) \ + do \ + { \ + switch (bpp) \ + { \ + case 0: /*8 bpp*/ \ + vram[addr & 0x3fffff] = val; \ + virge->svga.changedvram[(addr & 0x3fffff) >> 12] = changeframecount; \ + break; \ + case 1: /*16 bpp*/ \ + *(uint16_t *)&vram[addr & 0x3fffff] = val; \ + virge->svga.changedvram[(addr & 0x3fffff) >> 12] = changeframecount; \ + break; \ + case 2: /*24 bpp*/ \ + *(uint32_t *)&vram[addr & 0x3fffff] = (val & 0xffffff) | \ + (vram[(addr + 3) & 0x3fffff] << 24); \ + virge->svga.changedvram[(addr & 0x3fffff) >> 12] = changeframecount; \ + break; \ + } \ + } while (0) + +static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) +{ + uint8_t *vram = virge->svga.vram; + uint32_t mono_pattern[64]; + int count_mask; + int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; + int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; + int bpp; + int x_mul; + int cpu_dat_shift; + uint32_t *pattern_data; + uint32_t src_addr; + uint32_t dest_addr; + uint32_t source = 0, dest, pattern; + uint32_t out = 0; + int update; + + switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) + { + case CMD_SET_FORMAT_8: + bpp = 0; + x_mul = 1; + cpu_dat_shift = 8; + pattern_data = virge->s3d.pattern_8; + break; + case CMD_SET_FORMAT_16: + bpp = 1; + x_mul = 2; + cpu_dat_shift = 16; + pattern_data = virge->s3d.pattern_16; + break; + case CMD_SET_FORMAT_24: + default: + bpp = 2; + x_mul = 3; + cpu_dat_shift = 24; + pattern_data = virge->s3d.pattern_32; + break; + } + if (virge->s3d.cmd_set & CMD_SET_MP) + pattern_data = mono_pattern; + + switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) + { + case CMD_SET_ITA_BYTE: + count_mask = ~0x7; + break; + case CMD_SET_ITA_WORD: + count_mask = ~0xf; + break; + case CMD_SET_ITA_DWORD: + default: + count_mask = ~0x1f; + break; + } + if (virge->s3d.cmd_set & CMD_SET_MP) + { + int x, y; + for (y = 0; y < 4; y++) + { + for (x = 0; x < 8; x++) + { + if (virge->s3d.mono_pat_0 & (1 << (x + y*8))) + mono_pattern[y*8 + x] = virge->s3d.pat_fg_clr; + else + mono_pattern[y*8 + x] = virge->s3d.pat_bg_clr; + if (virge->s3d.mono_pat_1 & (1 << (x + y*8))) + mono_pattern[(y+4)*8 + x] = virge->s3d.pat_fg_clr; + else + mono_pattern[(y+4)*8 + x] = virge->s3d.pat_bg_clr; + } + } + } + switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK) + { + case CMD_SET_COMMAND_NOP: + break; + + case CMD_SET_COMMAND_BITBLT: + if (count == -1) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.data_left_count = 0; + +/* pclog("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n", + virge->s3d.src_x, + virge->s3d.src_y, + virge->s3d.dest_x, + virge->s3d.dest_y, + virge->s3d.w, + virge->s3d.h, + virge->s3d.rop, + virge->s3d.src_base, + virge->s3d.dest_base);*/ + + if (virge->s3d.cmd_set & CMD_SET_IDS) + return; + } + if (!virge->s3d.h) + return; + while (count) + { + src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + (virge->s3d.src_y * virge->s3d.src_str); + dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + out = 0; + update = 1; + + switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) + { + case 0: + case CMD_SET_MS: + READ(src_addr, source); + if ((virge->s3d.cmd_set & CMD_SET_TP) && source == virge->s3d.src_fg_clr) + update = 0; + break; + case CMD_SET_IDS: + if (virge->s3d.data_left_count) + { + /*Handle shifting for 24-bit data*/ + source = virge->s3d.data_left; + source |= ((cpu_dat << virge->s3d.data_left_count) & ~0xff000000); + cpu_dat >>= (cpu_dat_shift - virge->s3d.data_left_count); + count -= (cpu_dat_shift - virge->s3d.data_left_count); + virge->s3d.data_left_count = 0; + if (count < cpu_dat_shift) + { + virge->s3d.data_left = cpu_dat; + virge->s3d.data_left_count = count; + count = 0; + } + } + else + { + source = cpu_dat; + cpu_dat >>= cpu_dat_shift; + count -= cpu_dat_shift; + if (count < cpu_dat_shift) + { + virge->s3d.data_left = cpu_dat; + virge->s3d.data_left_count = count; + count = 0; + } + } + if ((virge->s3d.cmd_set & CMD_SET_TP) && source == virge->s3d.src_fg_clr) + update = 0; + break; + case CMD_SET_IDS | CMD_SET_MS: + source = (cpu_dat & (1 << 31)) ? virge->s3d.src_fg_clr : virge->s3d.src_bg_clr; + if ((virge->s3d.cmd_set & CMD_SET_TP) && !(cpu_dat & (1 << 31))) + update = 0; + cpu_dat <<= 1; + count--; + break; + } + + CLIP(virge->s3d.dest_x, virge->s3d.dest_y); + + if (update) + { + READ(dest_addr, dest); + pattern = pattern_data[(virge->s3d.dest_y & 7)*8 + (virge->s3d.dest_x & 7)]; + MIX(); + + WRITE(dest_addr, out); + } + + virge->s3d.src_x += x_inc; + virge->s3d.src_x &= 0x7ff; + virge->s3d.dest_x += x_inc; + virge->s3d.dest_x &= 0x7ff; + if (!virge->s3d.w) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.w = virge->s3d.r_width; + + virge->s3d.src_y += y_inc; + virge->s3d.dest_y += y_inc; + virge->s3d.h--; + + switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) + { + case CMD_SET_IDS: + cpu_dat >>= (count - (count & count_mask)); + count &= count_mask; + virge->s3d.data_left_count = 0; + break; + + case CMD_SET_IDS | CMD_SET_MS: + cpu_dat <<= (count - (count & count_mask)); + count &= count_mask; + break; + } + if (!virge->s3d.h) + { + return; + } + } + else + virge->s3d.w--; + } + break; + + case CMD_SET_COMMAND_RECTFILL: + /*No source, pattern = pat_fg_clr*/ + if (count == -1) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + +/* pclog("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, + virge->s3d.dest_y, + virge->s3d.w, + virge->s3d.h, + virge->s3d.rop, virge->s3d.dest_base);*/ + } + + while (count && virge->s3d.h) + { + uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0, dest, pattern = virge->s3d.pat_fg_clr; + uint32_t out = 0; + int update = 1; + + CLIP(virge->s3d.dest_x, virge->s3d.dest_y); + + if (update) + { + READ(dest_addr, dest); + + MIX(); + + WRITE(dest_addr, out); + } + + virge->s3d.src_x += x_inc; + virge->s3d.src_x &= 0x7ff; + virge->s3d.dest_x += x_inc; + virge->s3d.dest_x &= 0x7ff; + if (!virge->s3d.w) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.w = virge->s3d.r_width; + + virge->s3d.src_y += y_inc; + virge->s3d.dest_y += y_inc; + virge->s3d.h--; + if (!virge->s3d.h) + { + return; + } + } + else + virge->s3d.w--; + count--; + } + break; + + case CMD_SET_COMMAND_LINE: + if (count == -1) + { + virge->s3d.dest_x = virge->s3d.lxstart; + virge->s3d.dest_y = virge->s3d.lystart; + virge->s3d.h = virge->s3d.lycnt; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + } + while (virge->s3d.h) + { + int x; + int new_x; + int first_pixel = 1; + + x = virge->s3d.dest_x >> 20; + + if (virge->s3d.h == virge->s3d.lycnt && + ((virge->s3d.line_dir && x > virge->s3d.lxend0) || + (!virge->s3d.line_dir && x < virge->s3d.lxend0))) + x = virge->s3d.lxend0; + + if (virge->s3d.h == 1) + new_x = virge->s3d.lxend1 + (virge->s3d.line_dir ? 1 : -1); + else + new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20; + + + if ((virge->s3d.line_dir && x > new_x) || + (!virge->s3d.line_dir && x < new_x)) + goto skip_line; + + do + { + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0, dest, pattern; + uint32_t out = 0; + int update = 1; + + if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && + ((virge->s3d.line_dir && x < virge->s3d.lxend0) || + (!virge->s3d.line_dir && x > virge->s3d.lxend0))) + update = 0; + + if ((virge->s3d.h == 1 || !first_pixel) && + ((virge->s3d.line_dir && x > virge->s3d.lxend1) || + (!virge->s3d.line_dir && x < virge->s3d.lxend1))) + update = 0; + + CLIP(x, virge->s3d.dest_y); + + if (update) + { + READ(dest_addr, dest); + pattern = virge->s3d.pat_fg_clr; + + MIX(); + + WRITE(dest_addr, out); + } + + if (x < new_x) + x++; + else if (x > new_x) + x--; + first_pixel = 0; + } while (x != new_x); + +skip_line: + virge->s3d.dest_x += virge->s3d.ldx; + virge->s3d.dest_y--; + virge->s3d.h--; + } + break; + + case CMD_SET_COMMAND_POLY: + /*No source*/ + if (virge->s3d.pycnt & (1 << 28)) + virge->s3d.dest_r = virge->s3d.prxstart; + if (virge->s3d.pycnt & (1 << 29)) + virge->s3d.dest_l = virge->s3d.plxstart; + virge->s3d.h = virge->s3d.pycnt & 0x7ff; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + while (virge->s3d.h) + { + int x = virge->s3d.dest_l >> 20; + int xend = virge->s3d.dest_r >> 20; + int y = virge->s3d.pystart & 0x7ff; + int xdir = (x < xend) ? 1 : -1; + do + { + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); + uint32_t source = 0, dest, pattern; + uint32_t out = 0; + int update = 1; + + CLIP(x, y); + + if (update) + { + READ(dest_addr, dest); + pattern = pattern_data[(y & 7)*8 + (x & 7)]; + MIX(); + + WRITE(dest_addr, out); + } + + x = (x + xdir) & 0x7ff; + } + while (x != (xend + xdir)); + + virge->s3d.dest_l += virge->s3d.pldx; + virge->s3d.dest_r += virge->s3d.prdx; + virge->s3d.h--; + virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; + } + break; + + default: + fatal("s3_virge_bitblt : blit command %i %08x\n", (virge->s3d.cmd_set >> 27) & 0xf, virge->s3d.cmd_set); + } +} + +#define RGB15_TO_24(val, r, g, b) b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \ + g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ + r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); + +#define RGB24_TO_24(val, r, g, b) b = val & 0xff; \ + g = (val & 0xff00) >> 8; \ + r = (val & 0xff0000) >> 16 + +#define RGB15(r, g, b, dest) \ + if (virge->dithering_enabled) \ + { \ + int add = dither[_y & 3][_x & 3]; \ + int _r = (r > 248) ? 248 : r+add; \ + int _g = (g > 248) ? 248 : g+add; \ + int _b = (b > 248) ? 248 : b+add; \ + dest = ((_b >> 3) & 0x1f) | (((_g >> 3) & 0x1f) << 5) | (((_r >> 3) & 0x1f) << 10); \ + } \ + else \ + dest = ((b >> 3) & 0x1f) | (((g >> 3) & 0x1f) << 5) | (((r >> 3) & 0x1f) << 10) + +#define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) + +typedef struct rgba_t +{ + int r, g, b, a; +} rgba_t; + +typedef struct s3d_state_t +{ + int32_t r, g, b, a, u, v, d, w; + + int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w; + + uint32_t base_z; + + uint32_t tbu, tbv; + + uint32_t cmd_set; + int max_d; + + uint16_t *texture[10]; + + uint32_t tex_bdr_clr; + + int32_t x1, x2; + int y; + + rgba_t dest_rgba; +} s3d_state_t; + +typedef struct s3d_texture_state_t +{ + int level; + int texture_shift; + + int32_t u, v; +} s3d_texture_state_t; + +static void (*tex_read)(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out); +static void (*tex_sample)(s3d_state_t *state); +static void (*dest_pixel)(s3d_state_t *state); + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +static int _x, _y; + +static void tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; + + out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); + out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); + out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); + out->a = (val & 0x8000) ? 0xff : 0; +} + +static void tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; + + if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) + val = state->tex_bdr_clr; + + out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); + out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); + out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); + out->a = (val & 0x8000) ? 0xff : 0; +} + +static void tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; + + out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); + out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); + out->b = ((val & 0x000f) << 4) | (val & 0x000f); + out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); +} + +static void tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; + + if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) + val = state->tex_bdr_clr; + + out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); + out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); + out->b = ((val & 0x000f) << 4) | (val & 0x000f); + out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); +} + +static void tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; + + out->r = (val >> 16) & 0xff; + out->g = (val >> 8) & 0xff; + out->b = val & 0xff; + out->a = (val >> 24) & 0xff; +} +static void tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +{ + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; + + if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) + val = state->tex_bdr_clr; + + out->r = (val >> 16) & 0xff; + out->g = (val >> 8) & 0xff; + out->b = val & 0xff; + out->a = (val >> 24) & 0xff; +} + +static void tex_sample_normal(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); +} + +static void tex_sample_normal_filter(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int tex_offset; + rgba_t tex_samples[4]; + int du, dv; + int d[4]; + + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; + + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[0]); + du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; + + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[1]); + + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); + + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; +} + +static void tex_sample_mipmap(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); +} + +static void tex_sample_mipmap_filter(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int tex_offset; + rgba_t tex_samples[4]; + int du, dv; + int d[4]; + + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; + + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[0]); + du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; + + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[1]); + + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); + + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; +} + +static void tex_sample_persp_normal(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); +} + +static void tex_sample_persp_normal_filter(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0, u, v; + int tex_offset; + rgba_t tex_samples[4]; + int du, dv; + int d[4]; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; + + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); + + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); + + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; +} + +static void tex_sample_persp_normal_375(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); +} + +static void tex_sample_persp_normal_filter_375(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0, u, v; + int tex_offset; + rgba_t tex_samples[4]; + int du, dv; + int d[4]; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; + + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); + + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); + + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; +} + + +static void tex_sample_persp_mipmap(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); +} + +static void tex_sample_persp_mipmap_filter(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0, u, v; + int tex_offset; + rgba_t tex_samples[4]; + int du, dv; + int d[4]; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; + + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); + + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); + + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; +} + +static void tex_sample_persp_mipmap_375(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); +} + +static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) +{ + s3d_texture_state_t texture_state; + int32_t w = 0, u, v; + int tex_offset; + rgba_t tex_samples[4]; + int du, dv; + int d[4]; + + if (state->w) + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; + + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); + + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); + + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; +} + + +#define CLAMP(x) do \ + { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } \ + while (0) + +#define CLAMP_RGBA(r, g, b, a) \ + if ((r) & ~0xff) \ + r = ((r) < 0) ? 0 : 0xff; \ + if ((g) & ~0xff) \ + g = ((g) < 0) ? 0 : 0xff; \ + if ((b) & ~0xff) \ + b = ((b) < 0) ? 0 : 0xff; \ + if ((a) & ~0xff) \ + a = ((a) < 0) ? 0 : 0xff; + +#define CLAMP_RGB(r, g, b) do \ + { \ + if ((r) < 0) \ + r = 0; \ + if ((r) > 0xff) \ + r = 0xff; \ + if ((g) < 0) \ + g = 0; \ + if ((g) > 0xff) \ + g = 0xff; \ + if ((b) < 0) \ + b = 0; \ + if ((b) > 0xff) \ + b = 0xff; \ + } \ + while (0) + +static void dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) +{ + state->dest_rgba.r = state->r >> 7; + CLAMP(state->dest_rgba.r); + + state->dest_rgba.g = state->g >> 7; + CLAMP(state->dest_rgba.g); + + state->dest_rgba.b = state->b >> 7; + CLAMP(state->dest_rgba.b); + + state->dest_rgba.a = state->a >> 7; + CLAMP(state->dest_rgba.a); +} + +static void dest_pixel_unlit_texture_triangle(s3d_state_t *state) +{ + tex_sample(state); + + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a = state->a >> 7; +} + +static void dest_pixel_lit_texture_decal(s3d_state_t *state) +{ + tex_sample(state); + + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a = state->a >> 7; +} + +static void dest_pixel_lit_texture_reflection(s3d_state_t *state) +{ + tex_sample(state); + + state->dest_rgba.r += (state->r >> 7); + state->dest_rgba.g += (state->g >> 7); + state->dest_rgba.b += (state->b >> 7); + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a += (state->a >> 7); + + CLAMP_RGBA(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, state->dest_rgba.a); +} + +static void dest_pixel_lit_texture_modulate(s3d_state_t *state) +{ + int r = state->r >> 7, g = state->g >> 7, b = state->b >> 7, a = state->a >> 7; + + tex_sample(state); + + CLAMP_RGBA(r, g, b, a); + + state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8; + state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; + state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; + + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a = a; +} + +static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) +{ + uint8_t *vram = virge->svga.vram; + + int x_dir = s3d_tri->tlr ? 1 : -1; + + int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); + + int y_count = yc; + + int bpp = (s3d_tri->cmd_set >> 2) & 7; + + uint32_t dest_offset, z_offset; + + uint32_t src_col; + int src_r = 0, src_g = 0, src_b = 0; + + int x; + int xe; + uint32_t z; + + uint32_t dest_addr, z_addr; + int dx; + int x_offset; + int xz_offset; + + int update; + uint16_t src_z = 0; + + if (s3d_tri->cmd_set & CMD_SET_HC) + { + if (state->y < s3d_tri->clip_t) + return; + if (state->y > s3d_tri->clip_b) + { + int diff_y = state->y - s3d_tri->clip_b; + + if (diff_y > y_count) + diff_y = y_count; + + state->base_u += (s3d_tri->TdUdY * diff_y); + state->base_v += (s3d_tri->TdVdY * diff_y); + state->base_z += (s3d_tri->TdZdY * diff_y); + state->base_r += (s3d_tri->TdRdY * diff_y); + state->base_g += (s3d_tri->TdGdY * diff_y); + state->base_b += (s3d_tri->TdBdY * diff_y); + state->base_a += (s3d_tri->TdAdY * diff_y); + state->base_d += (s3d_tri->TdDdY * diff_y); + state->base_w += (s3d_tri->TdWdY * diff_y); + state->x1 += (dx1 * diff_y); + state->x2 += (dx2 * diff_y); + state->y -= diff_y; + dest_offset -= s3d_tri->dest_str; + z_offset -= s3d_tri->z_str; + y_count -= diff_y; + } + if ((state->y - y_count) < s3d_tri->clip_t) + y_count = state->y - s3d_tri->clip_t; + } + + dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); + z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); + + for (; y_count > 0; y_count--) + { + x = (state->x1 + ((1 << 20) - 1)) >> 20; + xe = (state->x2 + ((1 << 20) - 1)) >> 20; + z = (state->base_z > 0) ? (state->base_z << 1) : 0; + if (x_dir < 0) + { + x--; + xe--; + } + + if (((x != xe) && ((x_dir > 0) && (x < xe))) || ((x_dir < 0) && (x > xe))) + { + dx = (x_dir > 0) ? ((31 - ((state->x1-1) >> 15)) & 0x1f) : (((state->x1-1) >> 15) & 0x1f); + x_offset = x_dir * (bpp + 1); + xz_offset = x_dir << 1; + if (x_dir > 0) + dx += 1; + state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); + state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); + state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); + state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); + state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); + state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); + state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); + state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); + z += ((s3d_tri->TdZdX * dx) >> 5); + + if (s3d_tri->cmd_set & CMD_SET_HC) + { + if (x_dir > 0) + { + if (x > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + xe = s3d_tri->clip_r; + if (x < s3d_tri->clip_l) + { + int diff_x = s3d_tri->clip_l - x; + + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); + + x = s3d_tri->clip_l; + } + } + else + { + if (x < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + xe = s3d_tri->clip_l; + if (x > s3d_tri->clip_r) + { + int diff_x = x - s3d_tri->clip_r; + + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); + + x = s3d_tri->clip_r; + } + } + } + + virge->svga.changedvram[(dest_offset & 0x3fffff) >> 12] = changeframecount; + + dest_addr = dest_offset + (x * (bpp + 1)); + z_addr = z_offset + (x << 1); + + for (; x != xe; x = (x + x_dir) & 0xfff) + { + update = 1; + _x = x; _y = state->y; + + if (use_z) + { + src_z = Z_READ(z_addr); + Z_CLIP(src_z, z >> 16); + } + + if (update) + { + uint32_t dest_col; + + dest_pixel(state); + + if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) + { + switch (bpp) + { + case 0: /*8 bpp*/ + /*Not implemented yet*/ + break; + case 1: /*16 bpp*/ + src_col = *(uint16_t *)&vram[dest_addr & 0x3fffff]; + RGB15_TO_24(src_col, src_r, src_g, src_b); + break; + case 2: /*24 bpp*/ + src_col = (*(uint32_t *)&vram[dest_addr & 0x3fffff]) & 0xffffff; + RGB24_TO_24(src_col, src_r, src_g, src_b); + break; + } + + state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + (src_r * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + (src_g * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + (src_b * (255 - state->dest_rgba.a))) / 255; + } + + switch (bpp) + { + case 0: /*8 bpp*/ + /*Not implemented yet*/ + break; + case 1: /*16 bpp*/ + RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); + *(uint16_t *)&vram[dest_addr] = dest_col; + break; + case 2: /*24 bpp*/ + dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); + *(uint8_t *)&vram[dest_addr] = dest_col & 0xff; + *(uint8_t *)&vram[dest_addr + 1] = (dest_col >> 8) & 0xff; + *(uint8_t *)&vram[dest_addr + 2] = (dest_col >> 16) & 0xff; + break; + } + + if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) + Z_WRITE(z_addr, src_z); + } + + z += s3d_tri->TdZdX; + state->u += s3d_tri->TdUdX; + state->v += s3d_tri->TdVdX; + state->r += s3d_tri->TdRdX; + state->g += s3d_tri->TdGdX; + state->b += s3d_tri->TdBdX; + state->a += s3d_tri->TdAdX; + state->d += s3d_tri->TdDdX; + state->w += s3d_tri->TdWdX; + dest_addr += x_offset; + z_addr += xz_offset; + virge->pixel_count++; + } + } +tri_skip_line: + state->x1 += dx1; + state->x2 += dx2; + state->base_u += s3d_tri->TdUdY; + state->base_v += s3d_tri->TdVdY; + state->base_z += s3d_tri->TdZdY; + state->base_r += s3d_tri->TdRdY; + state->base_g += s3d_tri->TdGdY; + state->base_b += s3d_tri->TdBdY; + state->base_a += s3d_tri->TdAdY; + state->base_d += s3d_tri->TdDdY; + state->base_w += s3d_tri->TdWdY; + state->y--; + dest_offset -= s3d_tri->dest_str; + z_offset -= s3d_tri->z_str; + } +} + +static int tex_size[8] = +{ + 4*2, + 2*2, + 2*2, + 1*2, + 2/1, + 2/1, + 1*2, + 1*2 +}; + +static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) +{ + s3d_state_t state; + + uint32_t tex_base; + int c; + + uint64_t start_time = timer_read(); + uint64_t end_time; + + state.tbu = s3d_tri->tbu << 11; + state.tbv = s3d_tri->tbv << 11; + + state.max_d = (s3d_tri->cmd_set >> 8) & 15; + + state.tex_bdr_clr = s3d_tri->tex_bdr_clr; + + state.cmd_set = s3d_tri->cmd_set; + + state.base_u = s3d_tri->tus; + state.base_v = s3d_tri->tvs; + state.base_z = s3d_tri->tzs; + state.base_r = (int32_t)s3d_tri->trs; + state.base_g = (int32_t)s3d_tri->tgs; + state.base_b = (int32_t)s3d_tri->tbs; + state.base_a = (int32_t)s3d_tri->tas; + state.base_d = s3d_tri->tds; + state.base_w = s3d_tri->tws; + + tex_base = s3d_tri->tex_base; + for (c = 9; c >= 0; c--) + { + state.texture[c] = (uint16_t *)&virge->svga.vram[tex_base]; + if (c <= state.max_d) + tex_base += ((1 << (c*2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2; + } + + switch ((s3d_tri->cmd_set >> 27) & 0xf) + { + case 0: + dest_pixel = dest_pixel_gouraud_shaded_triangle; + break; + case 1: + case 5: + switch ((s3d_tri->cmd_set >> 15) & 0x3) + { + case 0: + dest_pixel = dest_pixel_lit_texture_reflection; + break; + case 1: + dest_pixel = dest_pixel_lit_texture_modulate; + break; + case 2: + dest_pixel = dest_pixel_lit_texture_decal; + break; + default: + pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); + return; + } + break; + case 2: + case 6: + dest_pixel = dest_pixel_unlit_texture_triangle; + break; + default: + pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); + return; + } + + switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0)) + { + case 0: case 1: + tex_sample = tex_sample_mipmap; + break; + case 2: case 3: + tex_sample = virge->bilinear_enabled ? tex_sample_mipmap_filter : tex_sample_mipmap; + break; + case 4: case 5: + tex_sample = tex_sample_normal; + break; + case 6: case 7: + tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal; + break; + case (0 | 8): case (1 | 8): + if (virge->is_375) + tex_sample = tex_sample_persp_mipmap_375; + else + tex_sample = tex_sample_persp_mipmap; + break; + case (2 | 8): case (3 | 8): + if (virge->is_375) + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; + else + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; + break; + case (4 | 8): case (5 | 8): + if (virge->is_375) + tex_sample = tex_sample_persp_normal_375; + else + tex_sample = tex_sample_persp_normal; + break; + case (6 | 8): case (7 | 8): + if (virge->is_375) + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; + else + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; + break; + } + + switch ((s3d_tri->cmd_set >> 5) & 7) + { + case 0: + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap; + break; + case 1: + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap; + break; + case 2: + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; + break; + default: + pclog("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; + break; + } + + state.y = s3d_tri->tys; + state.x1 = s3d_tri->txs; + state.x2 = s3d_tri->txend01; + tri(virge, s3d_tri, &state, s3d_tri->ty01, s3d_tri->TdXdY02, s3d_tri->TdXdY01); + state.x2 = s3d_tri->txend12; + tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12); + + virge->tri_count++; + + end_time = timer_read(); + + virge_time += end_time - start_time; +} + +static void render_thread(void *param) +{ + virge_t *virge = (virge_t *)param; + + while (1) + { + thread_wait_event(virge->wake_render_thread, -1); + thread_reset_event(virge->wake_render_thread); + virge->s3d_busy = 1; + while (!RB_EMPTY) + { + s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]); + virge->s3d_read_idx++; + + if (RB_ENTRIES == RB_SIZE - 1) + thread_set_event(virge->not_full_event); + } + virge->s3d_busy = 0; + virge->subsys_stat |= INT_S3D_DONE; + s3_virge_update_irqs(virge); + } +} + +static void queue_triangle(virge_t *virge) +{ + if (RB_FULL) + { + thread_reset_event(virge->not_full_event); + if (RB_FULL) + thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/ + } + virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri; + virge->s3d_write_idx++; + if (!virge->s3d_busy) + thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/ +} + +static void s3_virge_hwcursor_draw(svga_t *svga, int displine) +{ + virge_t *virge = (virge_t *)svga->p; + int x; + uint16_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; + int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + + 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]; + if (svga->crtc[0x55] & 0x10) + { + /*X11*/ + for (xx = 0; xx < 16; xx++) + { + if (offset >= svga->hwcursor_latch.x) + { + if (dat[0] & 0x8000) + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = virge->hwcursor_col[dat[1] >> 15]; + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + } + else + { + /*Windows*/ + for (xx = 0; xx < 16; xx++) + { + if (offset >= svga->hwcursor_latch.x) + { + if (!(dat[0] & 0x8000)) + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = virge->hwcursor_col[dat[1] >> 15]; + else if (dat[1] & 0x8000) + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + } + svga->hwcursor_latch.addr += 4; + } + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; +} + +#define DECODE_YCbCr() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 2; c++) \ + { \ + uint8_t y1, y2; \ + int8_t Cr, Cb; \ + int dR, dG, dB; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359*Cr) >> 8; \ + dG = (88*Cb + 183*Cr) >> 8; \ + dB = (453*Cb) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write+1] = y2 + dR; \ + CLAMP(r[x_write+1]); \ + g[x_write+1] = y2 - dG; \ + CLAMP(g[x_write+1]); \ + b[x_write+1] = y2 + dB; \ + CLAMP(b[x_write+1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) + +/*Both YUV formats are untested*/ +#define DECODE_YUV211() \ + do \ + { \ + uint8_t y1, y2, y3, y4; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + y2 = (298 * (src[2] - 16)) >> 8; \ + V = src[3] - 0x80; \ + y3 = (298 * (src[4] - 16)) >> 8; \ + y4 = (298 * (src[5] - 16)) >> 8; \ + src += 6; \ + \ + dR = (309*V) >> 8; \ + dG = (100*U + 208*V) >> 8; \ + dB = (516*U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write+1] = y2 + dR; \ + CLAMP(r[x_write+1]); \ + g[x_write+1] = y2 - dG; \ + CLAMP(g[x_write+1]); \ + b[x_write+1] = y2 + dB; \ + CLAMP(b[x_write+1]); \ + \ + r[x_write+2] = y3 + dR; \ + CLAMP(r[x_write+2]); \ + g[x_write+2] = y3 - dG; \ + CLAMP(g[x_write+2]); \ + b[x_write+2] = y3 + dB; \ + CLAMP(b[x_write+2]); \ + \ + r[x_write+3] = y4 + dR; \ + CLAMP(r[x_write+3]); \ + g[x_write+3] = y4 - dG; \ + CLAMP(g[x_write+3]); \ + b[x_write+3] = y4 + dB; \ + CLAMP(b[x_write+3]); \ + \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define DECODE_YUV422() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 2; c++) \ + { \ + uint8_t y1, y2; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + V = src[2] - 0x80; \ + y2 = (298 * (src[3] - 16)) >> 8; \ + src += 4; \ + \ + dR = (309*V) >> 8; \ + dG = (100*U + 208*V) >> 8; \ + dB = (516*U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write+1] = y2 + dR; \ + CLAMP(r[x_write+1]); \ + g[x_write+1] = y2 - dG; \ + CLAMP(g[x_write+1]); \ + b[x_write+1] = y2 + dB; \ + CLAMP(b[x_write+1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) + +#define DECODE_RGB555() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 4; c++) \ + { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ + b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define DECODE_RGB565() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 4; c++) \ + { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ + b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define DECODE_RGB888() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 4; c++) \ + { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 3; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define DECODE_XRGB8888() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 4; c++) \ + { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 4; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define OVERLAY_SAMPLE() \ + do \ + { \ + switch (virge->streams.sdif) \ + { \ + case 1: \ + DECODE_YCbCr(); \ + break; \ + case 2: \ + DECODE_YUV422(); \ + break; \ + case 3: \ + DECODE_RGB555(); \ + break; \ + case 4: \ + DECODE_YUV211(); \ + break; \ + case 5: \ + DECODE_RGB565(); \ + break; \ + case 6: \ + DECODE_RGB888(); \ + break; \ + case 7: \ + default: \ + DECODE_XRGB8888(); \ + break; \ + } \ + } while (0) + +static void s3_virge_overlay_draw(svga_t *svga, int displine) +{ + virge_t *virge = (virge_t *)svga->p; + int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1; + int h_acc = virge->streams.dda_horiz_accumulator; + int r[8], g[8], b[8]; + int x_size, x_read = 4, x_write = 4; + int x; + uint32_t *p; + uint8_t *src = &svga->vram[svga->overlay_latch.addr]; + int y_add = enable_overscan ? 16 : 0; + int x_add = enable_overscan ? 8 : 0; + + p = &((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add]; + + if ((offset + virge->streams.sec_w) > virge->streams.pri_w) + x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; + else + x_size = virge->streams.sec_w + 1; + + OVERLAY_SAMPLE(); + + for (x = 0; x < x_size; x++) + { + *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + + h_acc += virge->streams.k1_horiz_scale; + if (h_acc >= 0) + { + if ((x_read ^ (x_read + 1)) & ~3) + OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; + + h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale); + } + } + + svga->overlay_latch.v_acc += virge->streams.k1_vert_scale; + if (svga->overlay_latch.v_acc >= 0) + { + svga->overlay_latch.v_acc += (virge->streams.k2_vert_scale - virge->streams.k1_vert_scale); + svga->overlay_latch.addr += virge->streams.sec_stride; + } +} + +static uint8_t s3_virge_pci_read(int func, int addr, void *p) +{ + virge_t *virge = (virge_t *)p; + svga_t *svga = &virge->svga; + uint8_t ret = 0; + switch (addr) + { + case 0x00: ret = 0x33; break; /*'S3'*/ + case 0x01: ret = 0x53; break; + + case 0x02: ret = virge->virge_id_low; break; + case 0x03: ret = virge->virge_id_high; break; + + case 0x04: ret = virge->pci_regs[0x04] & 0x27; break; + + case 0x07: ret = virge->pci_regs[0x07] & 0x36; break; + + case 0x08: ret = 0; break; /*Revision ID*/ + case 0x09: ret = 0; break; /*Programming interface*/ + + case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ + case 0x0b: ret = 0x03; /*output = 3; */break; + + case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break; + + case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ + case 0x11: ret = 0x00; break; + case 0x12: ret = 0x00; break; + case 0x13: ret = svga->crtc[0x59] & 0xfc; break; + + case 0x30: ret = virge->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ + case 0x31: ret = 0x00; break; + case 0x32: ret = virge->pci_regs[0x32]; break; + case 0x33: ret = virge->pci_regs[0x33]; break; + + case 0x3c: ret = virge->pci_regs[0x3c]; break; + + case 0x3d: ret = 0x01; break; /*INTA*/ + + case 0x3e: ret = 0x04; break; + case 0x3f: ret = 0xff; break; + + } + return ret; +} + +static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + svga_t *svga = &virge->svga; + switch (addr) + { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x3d: case 0x3e: case 0x3f: + return; + + case PCI_REG_COMMAND: + if (val & PCI_COMMAND_IO) + { + io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + } + else + io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; + s3_virge_updatemapping(virge); + return; + case 0x07: + virge->pci_regs[0x07] = val & 0x3e; + return; + case 0x0d: + virge->pci_regs[0x0d] = val & 0xf8; + return; + + case 0x13: + svga->crtc[0x59] = val & 0xfc; + s3_virge_updatemapping(virge); + return; + + case 0x30: case 0x32: case 0x33: + virge->pci_regs[addr] = val; + if (virge->pci_regs[0x30] & 0x01) + { + uint32_t addr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); + mem_mapping_set_addr(&virge->bios_rom.mapping, addr, 0x8000); + mem_mapping_enable(&virge->bios_rom.mapping); + } + else + { + mem_mapping_disable(&virge->bios_rom.mapping); + } + return; + case 0x3c: + virge->pci_regs[0x3c] = val; + return; + } +} + +static void *s3_virge_init() +{ + virge_t *virge = malloc(sizeof(virge_t)); + memset(virge, 0, sizeof(virge_t)); + + virge->bilinear_enabled = device_get_config_int("bilinear"); + virge->dithering_enabled = device_get_config_int("dithering"); + virge->memory_size = device_get_config_int("memory"); + + svga_init(&virge->svga, virge, virge->memory_size << 20, + s3_virge_recalctimings, + s3_virge_in, s3_virge_out, + s3_virge_hwcursor_draw, + s3_virge_overlay_draw); + virge->svga.vblank_start = s3_virge_vblank_start; + + rom_init(&virge->bios_rom, L"roms/video/s3virge/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&virge->bios_rom.mapping); + + mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, + svga_readw_linear, + svga_readl_linear, + svga_write_linear, + svga_writew_linear, + svga_writel_linear, + NULL, + 0, + &virge->svga); + + io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + + virge->pci_regs[4] = 3; + virge->pci_regs[5] = 0; + virge->pci_regs[6] = 0; + virge->pci_regs[7] = 2; + virge->pci_regs[0x32] = 0x0c; + virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3e] = 4; + virge->pci_regs[0x3f] = 0xff; + + virge->virge_id_high = 0x56; + virge->virge_id_low = 0x31; + virge->virge_rev = 0; + virge->virge_id = 0xe1; + + switch (virge->memory_size) + { + case 2: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); + break; + case 4: + default: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); + break; + } + + virge->svga.crtc[0x37] = 1; + virge->svga.crtc[0x53] = 1 << 3; + virge->svga.crtc[0x59] = 0x70; + + virge->is_375 = 0; + + virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); + + virge->wake_render_thread = thread_create_event(); + virge->wake_main_thread = thread_create_event(); + virge->not_full_event = thread_create_event(); + virge->render_thread = thread_create(render_thread, virge); + + virge->wake_fifo_thread = thread_create_event(); + virge->fifo_not_full_event = thread_create_event(); + virge->fifo_thread = thread_create(fifo_thread, virge); + + return virge; +} + +static void *s3_virge_988_init() +{ + virge_t *virge = malloc(sizeof(virge_t)); + memset(virge, 0, sizeof(virge_t)); + + virge->bilinear_enabled = device_get_config_int("bilinear"); + virge->dithering_enabled = device_get_config_int("dithering"); + virge->memory_size = device_get_config_int("memory"); + + svga_init(&virge->svga, virge, virge->memory_size << 20, + s3_virge_recalctimings, + s3_virge_in, s3_virge_out, + s3_virge_hwcursor_draw, + s3_virge_overlay_draw); + + rom_init(&virge->bios_rom, L"roms/video/s3virge/diamondstealth3000.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&virge->bios_rom.mapping); + + mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, + svga_readw_linear, + svga_readl_linear, + svga_write_linear, + svga_writew_linear, + svga_writel_linear, + NULL, + 0, + &virge->svga); + + io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + + virge->pci_regs[4] = 3; + virge->pci_regs[5] = 0; + virge->pci_regs[6] = 0; + virge->pci_regs[7] = 2; + virge->pci_regs[0x32] = 0x0c; + virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3e] = 4; + virge->pci_regs[0x3f] = 0xff; + + virge->virge_id_high = 0x88; + virge->virge_id_low = 0x3d; + virge->virge_rev = 0; + virge->virge_id = 0xe1; + + switch (virge->memory_size) + { + case 2: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); + break; + case 4: + default: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); + break; + } + + virge->svga.crtc[0x37] = 1; + virge->svga.crtc[0x53] = 1 << 3; + virge->svga.crtc[0x59] = 0x70; + + virge->is_375 = 0; + + virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); + + virge->wake_render_thread = thread_create_event(); + virge->wake_main_thread = thread_create_event(); + virge->not_full_event = thread_create_event(); + virge->render_thread = thread_create(render_thread, virge); + + virge->wake_fifo_thread = thread_create_event(); + virge->fifo_not_full_event = thread_create_event(); + virge->fifo_thread = thread_create(fifo_thread, virge); + + return virge; +} + +static void *s3_virge_375_init(wchar_t *romfn) +{ + virge_t *virge = malloc(sizeof(virge_t)); + memset(virge, 0, sizeof(virge_t)); + + virge->bilinear_enabled = device_get_config_int("bilinear"); + virge->dithering_enabled = device_get_config_int("dithering"); + virge->memory_size = device_get_config_int("memory"); + + svga_init(&virge->svga, virge, virge->memory_size << 20, + s3_virge_recalctimings, + s3_virge_in, s3_virge_out, + s3_virge_hwcursor_draw, + s3_virge_overlay_draw); + + rom_init(&virge->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&virge->bios_rom.mapping); + + mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, + svga_readw_linear, + svga_readl_linear, + svga_write_linear, + svga_writew_linear, + svga_writel_linear, + NULL, + 0, + &virge->svga); + + io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + + virge->pci_regs[4] = 3; + virge->pci_regs[5] = 0; + virge->pci_regs[6] = 0; + virge->pci_regs[7] = 2; + virge->pci_regs[0x32] = 0x0c; + virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3e] = 4; + virge->pci_regs[0x3f] = 0xff; + + virge->virge_id_high = 0x8a; + virge->virge_id_low = 0x01; + virge->virge_rev = 0; + virge->virge_id = 0xe1; + + switch (virge->memory_size) + { + case 2: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); + break; + case 4: + default: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); + break; + } + virge->svga.crtc[0x37] = 1; + virge->svga.crtc[0x53] = 1 << 3; + virge->svga.crtc[0x59] = 0x70; + + virge->svga.crtc[0x6c] = 0x01; + + virge->is_375 = 1; + + virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); + + virge->wake_render_thread = thread_create_event(); + virge->wake_main_thread = thread_create_event(); + virge->not_full_event = thread_create_event(); + virge->render_thread = thread_create(render_thread, virge); + + virge->wake_fifo_thread = thread_create_event(); + virge->fifo_not_full_event = thread_create_event(); + virge->fifo_thread = thread_create(fifo_thread, virge); + + return virge; +} + +static void *s3_virge_375_1_init() +{ + return s3_virge_375_init(L"roms/video/s3virge/86c375_1.bin"); +} + +static void *s3_virge_375_4_init() +{ + return s3_virge_375_init(L"roms/video/s3virge/86c375_4.bin"); +} + +static void s3_virge_close(void *p) +{ + virge_t *virge = (virge_t *)p; +#if 0 + FILE *f = fopen("vram.dmp", "wb"); + fwrite(virge->svga.vram, 4 << 20, 1, f); + fclose(f); +#endif + + thread_kill(virge->render_thread); + thread_destroy_event(virge->not_full_event); + thread_destroy_event(virge->wake_main_thread); + thread_destroy_event(virge->wake_render_thread); + + thread_kill(virge->fifo_thread); + thread_destroy_event(virge->wake_fifo_thread); + thread_destroy_event(virge->fifo_not_full_event); + + svga_close(&virge->svga); + + free(virge); +} + +static int s3_virge_available() +{ + return rom_present(L"roms/video/s3virge/s3virge.bin"); +} + +static int s3_virge_988_available() +{ + return rom_present(L"roms/video/s3virge/diamondstealth3000.VBI"); +} + +static int s3_virge_375_1_available() +{ + return rom_present(L"roms/video/s3virge/86c375_1.bin"); +} + +static int s3_virge_375_4_available() +{ + return rom_present(L"roms/video/s3virge/86c375_4.bin"); +} + +static void s3_virge_speed_changed(void *p) +{ + virge_t *virge = (virge_t *)p; + + svga_recalctimings(&virge->svga); +} + +static void s3_virge_force_redraw(void *p) +{ + virge_t *virge = (virge_t *)p; + + virge->svga.fullchange = changeframecount; +} + +static void s3_virge_add_status_info(char *s, int max_len, void *p) +{ + virge_t *virge = (virge_t *)p; + char temps[256]; + uint64_t new_time = timer_read(); + uint64_t status_diff = new_time - status_time; + status_time = new_time; + + if (!status_diff) + status_diff = 1; + + svga_add_status_info(s, max_len, &virge->svga); + sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes %i reads\n\n", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes, reg_reads); + strncat(s, temps, max_len); + + virge->pixel_count = virge->tri_count = 0; + virge_time = 0; + reg_reads = 0; + reg_writes = 0; +} + +static device_config_t s3_virge_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 4, + { + { + "2 MB", 2 + }, + { + "4 MB", 4 + }, + { + "" + } + } + }, + { + "bilinear", "Bilinear filtering", CONFIG_BINARY, "", 1 + }, + { + "dithering", "Dithering", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } +}; + +device_t s3_virge_device = +{ + "Diamond Stealth 3D 2000 (S3 ViRGE)", + 0, + s3_virge_init, + s3_virge_close, + s3_virge_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; + +device_t s3_virge_988_device = +{ + "Diamond Stealth 3D 3000 (S3 ViRGE/VX)", + 0, + s3_virge_988_init, + s3_virge_close, + s3_virge_988_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; + +device_t s3_virge_375_device = +{ + "S3 ViRGE/DX", + 0, + s3_virge_375_1_init, + s3_virge_close, + s3_virge_375_1_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; + +device_t s3_virge_375_4_device = +{ + "S3 ViRGE/DX (VBE 2.0)", + 0, + s3_virge_375_4_init, + s3_virge_close, + s3_virge_375_4_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; From ddedef1a8a96e98052eb3e57326a319619eea6a8 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 27 Jul 2017 21:44:01 +0200 Subject: [PATCH 48/82] Moved vid_s3_virge.c to video folder. --- src/vid_s3_virge.c | 4190 -------------------------------------------- 1 file changed, 4190 deletions(-) delete mode 100644 src/vid_s3_virge.c diff --git a/src/vid_s3_virge.c b/src/vid_s3_virge.c deleted file mode 100644 index 997b707e4..000000000 --- a/src/vid_s3_virge.c +++ /dev/null @@ -1,4190 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*S3 ViRGE emulation*/ -#include -#include "../ibm.h" -#include "../io.h" -#include "../mem.h" -#include "../pci.h" -#include "../rom.h" -#include "../device.h" -#include "../win/plat_thread.h" -#include "video.h" -#include "vid_s3_virge.h" -#include "vid_svga.h" -#include "vid_svga_render.h" - - -static uint64_t virge_time = 0; -static uint64_t status_time = 0; -static int reg_writes = 0, reg_reads = 0; - -static int dither[4][4] = -{ - {0, 4, 1, 5}, - {6, 2, 7, 3}, - {1, 5, 0, 4}, - {7, 3, 6, 2}, -}; - -#define RB_SIZE 256 -#define RB_MASK (RB_SIZE - 1) - -#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx) -#define RB_FULL (RB_ENTRIES == RB_SIZE) -#define RB_EMPTY (!RB_ENTRIES) - -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) - -#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx) -#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= FIFO_SIZE) -#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx) - -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff - -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), - FIFO_WRITE_DWORD = (0x03 << 24) -}; - -typedef struct -{ - uint32_t addr_type; - uint32_t val; -} fifo_entry_t; - -typedef struct s3d_t -{ - uint32_t cmd_set; - int clip_l, clip_r, clip_t, clip_b; - - uint32_t dest_base; - uint32_t dest_str; - - uint32_t z_base; - uint32_t z_str; - - uint32_t tex_base; - uint32_t tex_bdr_clr; - uint32_t tbv, tbu; - int32_t TdVdX, TdUdX; - int32_t TdVdY, TdUdY; - uint32_t tus, tvs; - - int32_t TdZdX, TdZdY; - uint32_t tzs; - - int32_t TdWdX, TdWdY; - uint32_t tws; - - int32_t TdDdX, TdDdY; - uint32_t tds; - - int16_t TdGdX, TdBdX, TdRdX, TdAdX; - int16_t TdGdY, TdBdY, TdRdY, TdAdY; - uint32_t tgs, tbs, trs, tas; - - uint32_t TdXdY12; - uint32_t txend12; - uint32_t TdXdY01; - uint32_t txend01; - uint32_t TdXdY02; - uint32_t txs; - uint32_t tys; - int ty01, ty12, tlr; -} s3d_t; - -typedef struct virge_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; - mem_mapping_t new_mmio_mapping; - - rom_t bios_rom; - - svga_t svga; - - uint8_t bank; - uint8_t ma_ext; - int width; - int bpp; - - uint8_t virge_id, virge_id_high, virge_id_low, virge_rev; - - uint32_t linear_base, linear_size; - - uint8_t pci_regs[256]; - int card; - - int is_375; - - int bilinear_enabled; - int dithering_enabled; - int memory_size; - - int pixel_count, tri_count; - - thread_t *render_thread; - event_t *wake_render_thread; - event_t *wake_main_thread; - event_t *not_full_event; - - uint32_t hwcursor_col[2]; - int hwcursor_col_pos; - - struct - { - uint32_t src_base; - uint32_t dest_base; - int clip_l, clip_r, clip_t, clip_b; - int dest_str, src_str; - uint32_t mono_pat_0; - uint32_t mono_pat_1; - uint32_t pat_bg_clr; - uint32_t pat_fg_clr; - uint32_t src_bg_clr; - uint32_t src_fg_clr; - uint32_t cmd_set; - int r_width, r_height; - int rsrc_x, rsrc_y; - int rdest_x, rdest_y; - - int lxend0, lxend1; - int32_t ldx; - uint32_t lxstart, lystart; - int lycnt; - int line_dir; - - int src_x, src_y; - int dest_x, dest_y; - int w, h; - uint8_t rop; - - int data_left_count; - uint32_t data_left; - - uint32_t pattern_8[8*8]; - uint32_t pattern_16[8*8]; - uint32_t pattern_32[8*8]; - - uint32_t prdx; - uint32_t prxstart; - uint32_t pldx; - uint32_t plxstart; - uint32_t pystart; - uint32_t pycnt; - uint32_t dest_l, dest_r; - } s3d; - - s3d_t s3d_tri; - - s3d_t s3d_buffer[RB_SIZE]; - int s3d_read_idx, s3d_write_idx; - int s3d_busy; - - struct - { - uint32_t pri_ctrl; - uint32_t chroma_ctrl; - uint32_t sec_ctrl; - uint32_t chroma_upper_bound; - uint32_t sec_filter; - uint32_t blend_ctrl; - uint32_t pri_fb0, pri_fb1; - uint32_t pri_stride; - uint32_t buffer_ctrl; - uint32_t sec_fb0, sec_fb1; - uint32_t sec_stride; - uint32_t overlay_ctrl; - int32_t k1_vert_scale; - int32_t k2_vert_scale; - int32_t dda_vert_accumulator; - int32_t k1_horiz_scale; - int32_t k2_horiz_scale; - int32_t dda_horiz_accumulator; - uint32_t fifo_ctrl; - uint32_t pri_start; - uint32_t pri_size; - uint32_t sec_start; - uint32_t sec_size; - - int sdif; - - int pri_x, pri_y, pri_w, pri_h; - int sec_x, sec_y, sec_w, sec_h; - } streams; - - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; - - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - int virge_busy; - - uint8_t subsys_stat, subsys_cntl; -} virge_t; - -static __inline void wake_fifo_thread(virge_t *virge) -{ - thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static void queue_triangle(virge_t *virge); - -static void s3_virge_recalctimings(svga_t *svga); -static void s3_virge_updatemapping(virge_t *virge); - -static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); - -static uint8_t s3_virge_mmio_read(uint32_t addr, void *p); -static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p); -static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p); -static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p); -static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p); -static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p); - -enum -{ - CMD_SET_AE = 1, - CMD_SET_HC = (1 << 1), - - CMD_SET_FORMAT_MASK = (7 << 2), - CMD_SET_FORMAT_8 = (0 << 2), - CMD_SET_FORMAT_16 = (1 << 2), - CMD_SET_FORMAT_24 = (2 << 2), - - CMD_SET_MS = (1 << 6), - CMD_SET_IDS = (1 << 7), - CMD_SET_MP = (1 << 8), - CMD_SET_TP = (1 << 9), - - CMD_SET_ITA_MASK = (3 << 10), - CMD_SET_ITA_BYTE = (0 << 10), - CMD_SET_ITA_WORD = (1 << 10), - CMD_SET_ITA_DWORD = (2 << 10), - - CMD_SET_ZUP = (1 << 23), - - CMD_SET_ZB_MODE = (3 << 24), - - CMD_SET_XP = (1 << 25), - CMD_SET_YP = (1 << 26), - - CMD_SET_COMMAND_MASK = (15 << 27) -}; - -#define CMD_SET_ABC_SRC (1 << 18) -#define CMD_SET_ABC_ENABLE (1 << 19) -#define CMD_SET_TWE (1 << 26) - -enum -{ - CMD_SET_COMMAND_BITBLT = (0 << 27), - CMD_SET_COMMAND_RECTFILL = (2 << 27), - CMD_SET_COMMAND_LINE = (3 << 27), - CMD_SET_COMMAND_POLY = (5 << 27), - CMD_SET_COMMAND_NOP = (15 << 27) -}; - -#define INT_VSY (1 << 0) -#define INT_S3D_DONE (1 << 1) -#define INT_FIFO_OVF (1 << 2) -#define INT_FIFO_EMP (1 << 3) -#define INT_3DF_EMP (1 << 6) -#define INT_MASK 0xff - -static void s3_virge_update_irqs(virge_t *virge) -{ - if (!PCI) - { - return; - } - - if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK)) - pci_set_irq(virge->card, PCI_INTA); - else - pci_clear_irq(virge->card, PCI_INTA); -} - -static void s3_virge_out(uint16_t addr, uint8_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - uint8_t old; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c5: - if (svga->seqaddr >= 0x10) - { - svga->seqregs[svga->seqaddr & 0x1f]=val; - svga_recalctimings(svga); - return; - } - if (svga->seqaddr == 4) /*Chain-4 - update banking*/ - { - if (val & 8) svga->write_bank = svga->read_bank = virge->bank << 16; - else svga->write_bank = svga->read_bank = virge->bank << 14; - } - break; - - case 0x3d4: - svga->crtcreg = val; - return; - case 0x3d5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) - return; - if (svga->crtcreg >= 0x80) - return; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - switch (svga->crtcreg) - { - case 0x31: - virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4); - break; - case 0x32: - if ((svga->crtc[0x67] & 0xc) != 0xc) - svga->vrammask = (val & 0x40) ? 0x3ffff : ((virge->memory_size << 20) - 1); - s3_virge_update_irqs(virge); - break; - - case 0x50: - switch (svga->crtc[0x50] & 0xc1) - { - case 0x00: virge->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break; - case 0x01: virge->width = 1152; break; - case 0x40: virge->width = 640; break; - case 0x80: virge->width = 800; break; - case 0x81: virge->width = 1600; break; - case 0xc0: virge->width = 1280; break; - } - virge->bpp = (svga->crtc[0x50] >> 4) & 3; - break; - case 0x69: - virge->ma_ext = val & 0x1f; - break; - - case 0x35: - virge->bank = (virge->bank & 0x70) | (val & 0xf); - if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; - else svga->write_bank = svga->read_bank = virge->bank << 14; - break; - case 0x51: - virge->bank = (virge->bank & 0x4f) | ((val & 0xc) << 2); - if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; - else svga->write_bank = svga->read_bank = virge->bank << 14; - virge->ma_ext = (virge->ma_ext & ~0xc) | ((val & 3) << 2); - break; - case 0x6a: - virge->bank = val; - if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; - else svga->write_bank = svga->read_bank = virge->bank << 14; - break; - - case 0x3a: - if (val & 0x10) svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ - break; - - case 0x45: - svga->hwcursor.ena = val & 1; - break; - case 0x46: case 0x47: case 0x48: case 0x49: - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; - svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x4e] & 63; - svga->hwcursor.yoff = svga->crtc[0x4f] & 63; - svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - break; - - case 0x4a: - virge->hwcursor_col[1] = (virge->hwcursor_col[1] & ~(0xff << (virge->hwcursor_col_pos * 8))) | - (val << (virge->hwcursor_col_pos * 8)); - virge->hwcursor_col_pos++; - virge->hwcursor_col_pos &= 3; - break; - case 0x4b: - virge->hwcursor_col[0] = (virge->hwcursor_col[0] & ~(0xff << (virge->hwcursor_col_pos * 8))) | - (val << (virge->hwcursor_col_pos * 8)); - virge->hwcursor_col_pos++; - virge->hwcursor_col_pos &= 3; - break; - - case 0x53: - case 0x58: case 0x59: case 0x5a: - s3_virge_updatemapping(virge); - break; - - case 0x67: - switch (val >> 4) - { - case 2: case 3: svga->bpp = 15; break; - case 4: case 5: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - case 13: svga->bpp = (gfxcard == GFX_VIRGEVX) ? 24 : 32; break; - default: svga->bpp = 8; break; - } - break; - } - if (old != val) - { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) - { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; - } - svga_out(addr, val, svga); -} - -static uint8_t s3_virge_in(uint16_t addr, void *p) -{ - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - uint8_t ret; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c1: - if (svga->attraddr > 0x14) - ret = 0xff; - else - ret = svga_in(addr, svga); - break; - - case 0x3c5: - if (svga->seqaddr >= 8) - ret = svga->seqregs[svga->seqaddr & 0x1f]; - else if (svga->seqaddr <= 4) - ret = svga_in(addr, svga); - else - ret = 0xff; - break; - - case 0x3D4: - ret = svga->crtcreg; - break; - case 0x3D5: - switch (svga->crtcreg) - { - case 0x2d: ret = virge->virge_id_high; break; /*Extended chip ID*/ - case 0x2e: ret = virge->virge_id_low; break; /*New chip ID*/ - case 0x2f: ret = virge->virge_rev; break; - case 0x30: ret = virge->virge_id; break; /*Chip ID*/ - case 0x31: ret = (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); break; - case 0x35: ret = (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); break; - case 0x36: ret = (svga->crtc[0x36] & 0xfc) | 2; break; /*PCI bus*/ - case 0x45: virge->hwcursor_col_pos = 0; ret = svga->crtc[0x45]; break; - case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); break; - case 0x69: ret = virge->ma_ext; break; - case 0x6a: ret = virge->bank; break; - default: ret = svga->crtc[svga->crtcreg]; break; - } - break; - - default: - ret = svga_in(addr, svga); - break; - } - return ret; -} - -static void s3_virge_recalctimings(svga_t *svga) -{ - virge_t *virge = (virge_t *)svga->p; - - if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; - if (svga->crtc[0x5d] & 0x02) svga->hdisp += 0x100; - if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; - if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; - if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400; - if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; - if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; - svga->interlace = svga->crtc[0x42] & 0x20; - - if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ - { - svga->ma_latch |= (virge->ma_ext << 16); - if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; - else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; - if (!svga->rowoffset) svga->rowoffset = 256; - - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) - { - switch (svga->bpp) - { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - break; - case 16: - svga->render = svga_render_16bpp_highres; - break; - case 24: - svga->render = svga_render_24bpp_highres; - break; - case 32: - svga->render = svga_render_32bpp_highres; - break; - } - } - - if (gfxcard != GFX_VIRGEVX) - { - if ((svga->bpp == 15) || (svga->bpp == 16)) - { - svga->htotal >>= 1; - svga->hdisp >>= 1; - } - if (svga->bpp == 24) - { - svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ - } - } - svga->vrammask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : ((virge->memory_size << 20) - 1); - } - else /*Streams mode*/ - { - if (virge->streams.buffer_ctrl & 1) - svga->ma_latch = virge->streams.pri_fb1 >> 2; - else - svga->ma_latch = virge->streams.pri_fb0 >> 2; - - svga->hdisp = virge->streams.pri_w + 1; - if (virge->streams.pri_h < svga->dispend) - svga->dispend = virge->streams.pri_h; - - svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; - svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; - svga->overlay.ysize = virge->streams.sec_h; - - if (virge->streams.buffer_ctrl & 2) - svga->overlay.addr = virge->streams.sec_fb1; - else - svga->overlay.addr = virge->streams.sec_fb0; - - svga->overlay.ena = (svga->overlay.x >= 0); - svga->overlay.v_acc = virge->streams.dda_vert_accumulator; - svga->rowoffset = virge->streams.pri_stride >> 3; - - switch ((virge->streams.pri_ctrl >> 24) & 0x7) - { - case 0: /*RGB-8 (CLUT)*/ - svga->render = svga_render_8bpp_highres; - break; - case 3: /*KRGB-16 (1.5.5.5)*/ - svga->htotal >>= 1; - svga->render = svga_render_15bpp_highres; - break; - case 5: /*RGB-16 (5.6.5)*/ - svga->htotal >>= 1; - svga->render = svga_render_16bpp_highres; - break; - case 6: /*RGB-24 (8.8.8)*/ - svga->render = svga_render_24bpp_highres; - break; - case 7: /*XRGB-32 (X.8.8.8)*/ - svga->render = svga_render_32bpp_highres; - break; - } - svga->vrammask = (virge->memory_size << 20) - 1; - } - - if (((svga->miscout >> 2) & 3) == 3) - { - int n = svga->seqregs[0x12] & 0x1f; - int r = (svga->seqregs[0x12] >> 5) & ((virge->is_375 || (gfxcard == GFX_VIRGEVX)) ? 7 : 3); - int m = svga->seqregs[0x13] & 0x7f; - double freq = (((double)m + 2) / (((double)n + 2) * (double)(1 << r))) * 14318184.0; - - svga->clock = cpuclock / freq; - } -} - -static void s3_virge_updatemapping(virge_t *virge) -{ - svga_t *svga = &virge->svga; - - if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&virge->linear_mapping); - mem_mapping_disable(&virge->mmio_mapping); - mem_mapping_disable(&virge->new_mmio_mapping); - return; - } - - //pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); - switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - - virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - - //pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); - if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ - { - switch (svga->crtc[0x58] & 3) - { - case 0: /*64k*/ - virge->linear_size = 0x10000; - break; - case 1: /*1mb*/ - virge->linear_size = 0x100000; - break; - case 2: /*2mb*/ - virge->linear_size = 0x200000; - break; - case 3: /*8mb*/ - virge->linear_size = 0x400000; - break; - } - virge->linear_base &= ~(virge->linear_size - 1); - svga->linear_base = virge->linear_base; - //pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); - if (virge->linear_base == 0xa0000) - { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_disable(&virge->linear_mapping); - } - else - mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); - svga->fb_only = 1; - } - else - { - mem_mapping_disable(&virge->linear_mapping); - svga->fb_only = 0; - } - - //pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); - if (svga->crtc[0x53] & 0x10) /*Old MMIO*/ - { - if (svga->crtc[0x53] & 0x20) - mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); - else - mem_mapping_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000); - } - else - mem_mapping_disable(&virge->mmio_mapping); - - if (svga->crtc[0x53] & 0x08) /*New MMIO*/ - mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); - else - mem_mapping_disable(&virge->new_mmio_mapping); - -} - -static void s3_virge_vblank_start(svga_t *svga) -{ - virge_t *virge = (virge_t *)svga->p; - - virge->subsys_stat |= INT_VSY; - s3_virge_update_irqs(virge); -} - -static void s3_virge_wait_fifo_idle(virge_t *virge) -{ - while (!FIFO_EMPTY) - { - wake_fifo_thread(virge); - thread_wait_event(virge->fifo_not_full_event, 1); - } -} - -static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) -{ - virge_t *virge = (virge_t *)p; - uint8_t ret; - - reg_reads++; - switch (addr & 0xffff) - { - case 0x8505: - if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) - ret = 0x10; - else - ret = 0x10 | (1 << 5); - if (!virge->virge_busy) - wake_fifo_thread(virge); - return ret; - - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - return s3_virge_in(addr & 0x3ff, p); - } - return 0xff; -} -static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p) -{ - reg_reads++; - switch (addr & 0xfffe) - { - default: - return s3_virge_mmio_read(addr, p) | (s3_virge_mmio_read(addr + 1, p) << 8); - } - return 0xffff; -} -static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) -{ - virge_t *virge = (virge_t *)p; - uint32_t ret = 0xffffffff; - reg_reads++; - switch (addr & 0xfffc) - { - case 0x8180: - ret = virge->streams.pri_ctrl; - break; - case 0x8184: - ret = virge->streams.chroma_ctrl; - break; - case 0x8190: - ret = virge->streams.sec_ctrl; - break; - case 0x8194: - ret = virge->streams.chroma_upper_bound; - break; - case 0x8198: - ret = virge->streams.sec_filter; - break; - case 0x81a0: - ret = virge->streams.blend_ctrl; - break; - case 0x81c0: - ret = virge->streams.pri_fb0; - break; - case 0x81c4: - ret = virge->streams.pri_fb1; - break; - case 0x81c8: - ret = virge->streams.pri_stride; - break; - case 0x81cc: - ret = virge->streams.buffer_ctrl; - break; - case 0x81d0: - ret = virge->streams.sec_fb0; - break; - case 0x81d4: - ret = virge->streams.sec_fb1; - break; - case 0x81d8: - ret = virge->streams.sec_stride; - break; - case 0x81dc: - ret = virge->streams.overlay_ctrl; - break; - case 0x81e0: - ret = virge->streams.k1_vert_scale; - break; - case 0x81e4: - ret = virge->streams.k2_vert_scale; - break; - case 0x81e8: - ret = virge->streams.dda_vert_accumulator; - break; - case 0x81ec: - ret = virge->streams.fifo_ctrl; - break; - case 0x81f0: - ret = virge->streams.pri_start; - break; - case 0x81f4: - ret = virge->streams.pri_size; - break; - case 0x81f8: - ret = virge->streams.sec_start; - break; - case 0x81fc: - ret = virge->streams.sec_size; - break; - - case 0x8504: - if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) - ret = (0x10 << 8); - else - ret = (0x10 << 8) | (1 << 13); - ret |= virge->subsys_stat; - if (!virge->virge_busy) - wake_fifo_thread(virge); - break; - case 0xa4d4: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.src_base; - break; - case 0xa4d8: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.dest_base; - break; - case 0xa4dc: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; - break; - case 0xa4e0: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; - break; - case 0xa4e4: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; - break; - case 0xa4e8: case 0xace8: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.mono_pat_0; - break; - case 0xa4ec: case 0xacec: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.mono_pat_1; - break; - case 0xa4f0: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.pat_bg_clr; - break; - case 0xa4f4: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.pat_fg_clr; - break; - case 0xa4f8: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.src_bg_clr; - break; - case 0xa4fc: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.src_fg_clr; - break; - case 0xa500: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.cmd_set; - break; - case 0xa504: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; - break; - case 0xa508: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; - break; - case 0xa50c: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; - break; - - default: - ret = s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16); - } - return ret; -} - -static void fifo_thread(void *param) -{ - virge_t *virge = (virge_t *)param; - - while (1) - { - thread_set_event(virge->fifo_not_full_event); - thread_wait_event(virge->wake_fifo_thread, -1); - thread_reset_event(virge->wake_fifo_thread); - virge->virge_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK]; - uint32_t val = fifo->val; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) - s3_virge_bitblt(virge, 8, val); - break; - case FIFO_WRITE_WORD: - if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) - { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); - else - s3_virge_bitblt(virge, 16, val); - } - break; - case FIFO_WRITE_DWORD: - if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) - { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); - else - s3_virge_bitblt(virge, 32, val); - } - else - { - switch ((fifo->addr_type & FIFO_ADDR) & 0xfffc) - { - case 0xa000: case 0xa004: case 0xa008: case 0xa00c: - case 0xa010: case 0xa014: case 0xa018: case 0xa01c: - case 0xa020: case 0xa024: case 0xa028: case 0xa02c: - case 0xa030: case 0xa034: case 0xa038: case 0xa03c: - case 0xa040: case 0xa044: case 0xa048: case 0xa04c: - case 0xa050: case 0xa054: case 0xa058: case 0xa05c: - case 0xa060: case 0xa064: case 0xa068: case 0xa06c: - case 0xa070: case 0xa074: case 0xa078: case 0xa07c: - case 0xa080: case 0xa084: case 0xa088: case 0xa08c: - case 0xa090: case 0xa094: case 0xa098: case 0xa09c: - case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: - case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: - case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: - case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: - case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: - case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: - case 0xa100: case 0xa104: case 0xa108: case 0xa10c: - case 0xa110: case 0xa114: case 0xa118: case 0xa11c: - case 0xa120: case 0xa124: case 0xa128: case 0xa12c: - case 0xa130: case 0xa134: case 0xa138: case 0xa13c: - case 0xa140: case 0xa144: case 0xa148: case 0xa14c: - case 0xa150: case 0xa154: case 0xa158: case 0xa15c: - case 0xa160: case 0xa164: case 0xa168: case 0xa16c: - case 0xa170: case 0xa174: case 0xa178: case 0xa17c: - case 0xa180: case 0xa184: case 0xa188: case 0xa18c: - case 0xa190: case 0xa194: case 0xa198: case 0xa19c: - case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: - case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: - case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: - case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: - case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: - case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: - { - int x = (fifo->addr_type & FIFO_ADDR) & 4; - int y = ((fifo->addr_type & FIFO_ADDR) >> 3) & 7; - virge->s3d.pattern_8[y*8 + x] = val & 0xff; - virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; - virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; - virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; - - x = ((fifo->addr_type & FIFO_ADDR) >> 1) & 6; - y = ((fifo->addr_type & FIFO_ADDR) >> 4) & 7; - virge->s3d.pattern_16[y*8 + x] = val & 0xffff; - virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; - - x = ((fifo->addr_type & FIFO_ADDR) >> 2) & 7; - y = ((fifo->addr_type & FIFO_ADDR) >> 5) & 7; - virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; - } - break; - - case 0xa4d4: case 0xa8d4: - virge->s3d.src_base = val & 0x3ffff8; - break; - case 0xa4d8: case 0xa8d8: - virge->s3d.dest_base = val & 0x3ffff8; - break; - case 0xa4dc: case 0xa8dc: - virge->s3d.clip_l = (val >> 16) & 0x7ff; - virge->s3d.clip_r = val & 0x7ff; - break; - case 0xa4e0: case 0xa8e0: - virge->s3d.clip_t = (val >> 16) & 0x7ff; - virge->s3d.clip_b = val & 0x7ff; - break; - case 0xa4e4: case 0xa8e4: - virge->s3d.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xa4e8: case 0xace8: - virge->s3d.mono_pat_0 = val; - break; - case 0xa4ec: case 0xacec: - virge->s3d.mono_pat_1 = val; - break; - case 0xa4f0: case 0xacf0: - virge->s3d.pat_bg_clr = val; - break; - case 0xa4f4: case 0xa8f4: case 0xacf4: - virge->s3d.pat_fg_clr = val; - break; - case 0xa4f8: - virge->s3d.src_bg_clr = val; - break; - case 0xa4fc: - virge->s3d.src_fg_clr = val; - break; - case 0xa500: case 0xa900: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xa504: - virge->s3d.r_width = (val >> 16) & 0x7ff; - virge->s3d.r_height = val & 0x7ff; - break; - case 0xa508: - virge->s3d.rsrc_x = (val >> 16) & 0x7ff; - virge->s3d.rsrc_y = val & 0x7ff; - break; - case 0xa50c: - virge->s3d.rdest_x = (val >> 16) & 0x7ff; - virge->s3d.rdest_y = val & 0x7ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xa96c: - virge->s3d.lxend0 = (val >> 16) & 0x7ff; - virge->s3d.lxend1 = val & 0x7ff; - break; - case 0xa970: - virge->s3d.ldx = (int32_t)val; - break; - case 0xa974: - virge->s3d.lxstart = val; - break; - case 0xa978: - virge->s3d.lystart = val & 0x7ff; - break; - case 0xa97c: - virge->s3d.lycnt = val & 0x7ff; - virge->s3d.line_dir = val >> 31; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xad00: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xad68: - virge->s3d.prdx = val; - break; - case 0xad6c: - virge->s3d.prxstart = val; - break; - case 0xad70: - virge->s3d.pldx = val; - break; - case 0xad74: - virge->s3d.plxstart = val; - break; - case 0xad78: - virge->s3d.pystart = val & 0x7ff; - break; - case 0xad7c: - virge->s3d.pycnt = val & 0x300007ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xb4d4: - virge->s3d_tri.z_base = val & 0x3ffff8; - break; - case 0xb4d8: - virge->s3d_tri.dest_base = val & 0x3ffff8; - break; - case 0xb4dc: - virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_r = val & 0x7ff; - break; - case 0xb4e0: - virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_b = val & 0x7ff; - break; - case 0xb4e4: - virge->s3d_tri.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xb4e8: - virge->s3d_tri.z_str = val & 0xff8; - break; - case 0xb4ec: - virge->s3d_tri.tex_base = val & 0x3ffff8; - break; - case 0xb4f0: - virge->s3d_tri.tex_bdr_clr = val & 0xffffff; - break; - case 0xb500: - virge->s3d_tri.cmd_set = val; - if (!(val & CMD_SET_AE)) - queue_triangle(virge); - break; - case 0xb504: - virge->s3d_tri.tbv = val & 0xfffff; - break; - case 0xb508: - virge->s3d_tri.tbu = val & 0xfffff; - break; - case 0xb50c: - virge->s3d_tri.TdWdX = val; - break; - case 0xb510: - virge->s3d_tri.TdWdY = val; - break; - case 0xb514: - virge->s3d_tri.tws = val; - break; - case 0xb518: - virge->s3d_tri.TdDdX = val; - break; - case 0xb51c: - virge->s3d_tri.TdVdX = val; - break; - case 0xb520: - virge->s3d_tri.TdUdX = val; - break; - case 0xb524: - virge->s3d_tri.TdDdY = val; - break; - case 0xb528: - virge->s3d_tri.TdVdY = val; - break; - case 0xb52c: - virge->s3d_tri.TdUdY = val; - break; - case 0xb530: - virge->s3d_tri.tds = val; - break; - case 0xb534: - virge->s3d_tri.tvs = val; - break; - case 0xb538: - virge->s3d_tri.tus = val; - break; - case 0xb53c: - virge->s3d_tri.TdGdX = val >> 16; - virge->s3d_tri.TdBdX = val & 0xffff; - break; - case 0xb540: - virge->s3d_tri.TdAdX = val >> 16; - virge->s3d_tri.TdRdX = val & 0xffff; - break; - case 0xb544: - virge->s3d_tri.TdGdY = val >> 16; - virge->s3d_tri.TdBdY = val & 0xffff; - break; - case 0xb548: - virge->s3d_tri.TdAdY = val >> 16; - virge->s3d_tri.TdRdY = val & 0xffff; - break; - case 0xb54c: - virge->s3d_tri.tgs = (val >> 16) & 0xffff; - virge->s3d_tri.tbs = val & 0xffff; - break; - case 0xb550: - virge->s3d_tri.tas = (val >> 16) & 0xffff; - virge->s3d_tri.trs = val & 0xffff; - break; - - case 0xb554: - virge->s3d_tri.TdZdX = val; - break; - case 0xb558: - virge->s3d_tri.TdZdY = val; - break; - case 0xb55c: - virge->s3d_tri.tzs = val; - break; - case 0xb560: - virge->s3d_tri.TdXdY12 = val; - break; - case 0xb564: - virge->s3d_tri.txend12 = val; - break; - case 0xb568: - virge->s3d_tri.TdXdY01 = val; - break; - case 0xb56c: - virge->s3d_tri.txend01 = val; - break; - case 0xb570: - virge->s3d_tri.TdXdY02 = val; - break; - case 0xb574: - virge->s3d_tri.txs = val; - break; - case 0xb578: - virge->s3d_tri.tys = val; - break; - case 0xb57c: - virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; - virge->s3d_tri.ty12 = val & 0x7ff; - virge->s3d_tri.tlr = val >> 31; - if (virge->s3d_tri.cmd_set & CMD_SET_AE) - queue_triangle(virge); - break; - } - } - break; - } - - virge->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(virge->fifo_not_full_event); - - end_time = timer_read(); - virge_time += end_time - start_time; - } - virge->virge_busy = 0; - } -} - -static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) -{ - fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; - - if (FIFO_FULL) - { - thread_reset_event(virge->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } - - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; - - virge->fifo_write_idx++; - - /* if (FIFO_ENTRIES > 0xe000) - wake_fifo_thread(virge); */ - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(virge); -} - -static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - - reg_writes++; - if ((addr & 0xfffc) < 0x8000) - { - s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE); - } - else switch (addr & 0xffff) - { - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - s3_virge_out(addr & 0x3ff, val, p); - break; - } - - -} -static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - reg_writes++; - if ((addr & 0xfffc) < 0x8000) - { - s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD); - } - else switch (addr & 0xfffe) - { - case 0x83d4: - s3_virge_mmio_write(addr, val, p); - s3_virge_mmio_write(addr + 1, val >> 8, p); - break; - } -} -static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - reg_writes++; - - pclog("Write Address %x\n", addr & 0xe000); - - if ((addr & 0xfffc) < 0x8000) - { - s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); - } - else switch (addr & 0xfffc) - { - case 0: - s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - - case 0x8180: - virge->streams.pri_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x8184: - virge->streams.chroma_ctrl = val; - break; - case 0x8190: - virge->streams.sec_ctrl = val; - virge->streams.dda_horiz_accumulator = val & 0xfff; - if (val & (1 << 11)) - virge->streams.dda_horiz_accumulator |= 0xfffff800; - virge->streams.sdif = (val >> 24) & 7; - break; - case 0x8194: - virge->streams.chroma_upper_bound = val; - break; - case 0x8198: - virge->streams.sec_filter = val; - virge->streams.k1_horiz_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k1_horiz_scale |= 0xfffff800; - virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff; - if ((val >> 16) & (1 << 10)) - virge->streams.k2_horiz_scale |= 0xfffff800; - break; - case 0x81a0: - virge->streams.blend_ctrl = val; - break; - case 0x81c0: - virge->streams.pri_fb0 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81c4: - virge->streams.pri_fb1 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81c8: - virge->streams.pri_stride = val & 0xfff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81cc: - virge->streams.buffer_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d0: - virge->streams.sec_fb0 = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d4: - virge->streams.sec_fb1 = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d8: - virge->streams.sec_stride = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81dc: - virge->streams.overlay_ctrl = val; - break; - case 0x81e0: - virge->streams.k1_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k1_vert_scale |= 0xfffff800; - break; - case 0x81e4: - virge->streams.k2_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k2_vert_scale |= 0xfffff800; - break; - case 0x81e8: - virge->streams.dda_vert_accumulator = val & 0xfff; - if (val & (1 << 11)) - virge->streams.dda_vert_accumulator |= 0xfffff800; - break; - case 0x81ec: - virge->streams.fifo_ctrl = val; - break; - case 0x81f0: - virge->streams.pri_start = val; - virge->streams.pri_x = (val >> 16) & 0x7ff; - virge->streams.pri_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81f4: - virge->streams.pri_size = val; - virge->streams.pri_w = (val >> 16) & 0x7ff; - virge->streams.pri_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81f8: - virge->streams.sec_start = val; - virge->streams.sec_x = (val >> 16) & 0x7ff; - virge->streams.sec_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81fc: - virge->streams.sec_size = val; - virge->streams.sec_w = (val >> 16) & 0x7ff; - virge->streams.sec_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - - case 0x8504: - virge->subsys_stat &= ~(val & 0xff); - virge->subsys_cntl = (val >> 8); - s3_virge_update_irqs(virge); - break; - - case 0xa000: case 0xa004: case 0xa008: case 0xa00c: - case 0xa010: case 0xa014: case 0xa018: case 0xa01c: - case 0xa020: case 0xa024: case 0xa028: case 0xa02c: - case 0xa030: case 0xa034: case 0xa038: case 0xa03c: - case 0xa040: case 0xa044: case 0xa048: case 0xa04c: - case 0xa050: case 0xa054: case 0xa058: case 0xa05c: - case 0xa060: case 0xa064: case 0xa068: case 0xa06c: - case 0xa070: case 0xa074: case 0xa078: case 0xa07c: - case 0xa080: case 0xa084: case 0xa088: case 0xa08c: - case 0xa090: case 0xa094: case 0xa098: case 0xa09c: - case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: - case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: - case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: - case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: - case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: - case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: - case 0xa100: case 0xa104: case 0xa108: case 0xa10c: - case 0xa110: case 0xa114: case 0xa118: case 0xa11c: - case 0xa120: case 0xa124: case 0xa128: case 0xa12c: - case 0xa130: case 0xa134: case 0xa138: case 0xa13c: - case 0xa140: case 0xa144: case 0xa148: case 0xa14c: - case 0xa150: case 0xa154: case 0xa158: case 0xa15c: - case 0xa160: case 0xa164: case 0xa168: case 0xa16c: - case 0xa170: case 0xa174: case 0xa178: case 0xa17c: - case 0xa180: case 0xa184: case 0xa188: case 0xa18c: - case 0xa190: case 0xa194: case 0xa198: case 0xa19c: - case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: - case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: - case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: - case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: - case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: - case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: - { - int x = addr & 4; - int y = (addr >> 3) & 7; - virge->s3d.pattern_8[y*8 + x] = val & 0xff; - virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; - virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; - virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; - - x = (addr >> 1) & 6; - y = (addr >> 4) & 7; - virge->s3d.pattern_16[y*8 + x] = val & 0xffff; - virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; - - x = (addr >> 2) & 7; - y = (addr >> 5) & 7; - virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; - } - break; - - case 0xa4d4: case 0xa8d4: - virge->s3d.src_base = val & 0x3ffff8; - break; - case 0xa4d8: case 0xa8d8: - virge->s3d.dest_base = val & 0x3ffff8; - break; - case 0xa4dc: case 0xa8dc: - virge->s3d.clip_l = (val >> 16) & 0x7ff; - virge->s3d.clip_r = val & 0x7ff; - break; - case 0xa4e0: case 0xa8e0: - virge->s3d.clip_t = (val >> 16) & 0x7ff; - virge->s3d.clip_b = val & 0x7ff; - break; - case 0xa4e4: case 0xa8e4: - virge->s3d.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xa4e8: case 0xace8: - virge->s3d.mono_pat_0 = val; - break; - case 0xa4ec: case 0xacec: - virge->s3d.mono_pat_1 = val; - break; - case 0xa4f0: case 0xacf0: - virge->s3d.pat_bg_clr = val; - break; - case 0xa4f4: case 0xa8f4: case 0xacf4: - virge->s3d.pat_fg_clr = val; - break; - case 0xa4f8: - virge->s3d.src_bg_clr = val; - break; - case 0xa4fc: - virge->s3d.src_fg_clr = val; - break; - case 0xa500: case 0xa900: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xa504: - virge->s3d.r_width = (val >> 16) & 0x7ff; - virge->s3d.r_height = val & 0x7ff; - break; - case 0xa508: - virge->s3d.rsrc_x = (val >> 16) & 0x7ff; - virge->s3d.rsrc_y = val & 0x7ff; - break; - case 0xa50c: - virge->s3d.rdest_x = (val >> 16) & 0x7ff; - virge->s3d.rdest_y = val & 0x7ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xa96c: - virge->s3d.lxend0 = (val >> 16) & 0x7ff; - virge->s3d.lxend1 = val & 0x7ff; - break; - case 0xa970: - virge->s3d.ldx = (int32_t)val; - break; - case 0xa974: - virge->s3d.lxstart = val; - break; - case 0xa978: - virge->s3d.lystart = val & 0x7ff; - break; - case 0xa97c: - virge->s3d.lycnt = val & 0x7ff; - virge->s3d.line_dir = val >> 31; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xad00: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xad68: - virge->s3d.prdx = val; - break; - case 0xad6c: - virge->s3d.prxstart = val; - break; - case 0xad70: - virge->s3d.pldx = val; - break; - case 0xad74: - virge->s3d.plxstart = val; - break; - case 0xad78: - virge->s3d.pystart = val & 0x7ff; - break; - case 0xad7c: - virge->s3d.pycnt = val & 0x300007ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xb4d4: - virge->s3d_tri.z_base = val & 0x3ffff8; - break; - case 0xb4d8: - virge->s3d_tri.dest_base = val & 0x3ffff8; - break; - case 0xb4dc: - virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_r = val & 0x7ff; - break; - case 0xb4e0: - virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_b = val & 0x7ff; - break; - case 0xb4e4: - virge->s3d_tri.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xb4e8: - virge->s3d_tri.z_str = val & 0xff8; - break; - case 0xb4ec: - virge->s3d_tri.tex_base = val & 0x3ffff8; - break; - case 0xb4f0: - virge->s3d_tri.tex_bdr_clr = val & 0xffffff; - break; - case 0xb500: - virge->s3d_tri.cmd_set = val; - if (!(val & CMD_SET_AE)) - queue_triangle(virge); - break; - case 0xb504: - virge->s3d_tri.tbv = val & 0xfffff; - break; - case 0xb508: - virge->s3d_tri.tbu = val & 0xfffff; - break; - case 0xb50c: - virge->s3d_tri.TdWdX = val; - break; - case 0xb510: - virge->s3d_tri.TdWdY = val; - break; - case 0xb514: - virge->s3d_tri.tws = val; - break; - case 0xb518: - virge->s3d_tri.TdDdX = val; - break; - case 0xb51c: - virge->s3d_tri.TdVdX = val; - break; - case 0xb520: - virge->s3d_tri.TdUdX = val; - break; - case 0xb524: - virge->s3d_tri.TdDdY = val; - break; - case 0xb528: - virge->s3d_tri.TdVdY = val; - break; - case 0xb52c: - virge->s3d_tri.TdUdY = val; - break; - case 0xb530: - virge->s3d_tri.tds = val; - break; - case 0xb534: - virge->s3d_tri.tvs = val; - break; - case 0xb538: - virge->s3d_tri.tus = val; - break; - case 0xb53c: - virge->s3d_tri.TdGdX = val >> 16; - virge->s3d_tri.TdBdX = val & 0xffff; - break; - case 0xb540: - virge->s3d_tri.TdAdX = val >> 16; - virge->s3d_tri.TdRdX = val & 0xffff; - break; - case 0xb544: - virge->s3d_tri.TdGdY = val >> 16; - virge->s3d_tri.TdBdY = val & 0xffff; - break; - case 0xb548: - virge->s3d_tri.TdAdY = val >> 16; - virge->s3d_tri.TdRdY = val & 0xffff; - break; - case 0xb54c: - virge->s3d_tri.tgs = (val >> 16) & 0xffff; - virge->s3d_tri.tbs = val & 0xffff; - break; - case 0xb550: - virge->s3d_tri.tas = (val >> 16) & 0xffff; - virge->s3d_tri.trs = val & 0xffff; - break; - - case 0xb554: - virge->s3d_tri.TdZdX = val; - break; - case 0xb558: - virge->s3d_tri.TdZdY = val; - break; - case 0xb55c: - virge->s3d_tri.tzs = val; - break; - case 0xb560: - virge->s3d_tri.TdXdY12 = val; - break; - case 0xb564: - virge->s3d_tri.txend12 = val; - break; - case 0xb568: - virge->s3d_tri.TdXdY01 = val; - break; - case 0xb56c: - virge->s3d_tri.txend01 = val; - break; - case 0xb570: - virge->s3d_tri.TdXdY02 = val; - break; - case 0xb574: - virge->s3d_tri.txs = val; - break; - case 0xb578: - virge->s3d_tri.tys = val; - break; - case 0xb57c: - virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; - virge->s3d_tri.ty12 = val & 0x7ff; - virge->s3d_tri.tlr = val >> 31; - if (virge->s3d_tri.cmd_set & CMD_SET_AE) - queue_triangle(virge); - break; - } -} - -#define READ(addr, val) \ - do \ - { \ - switch (bpp) \ - { \ - case 0: /*8 bpp*/ \ - val = vram[addr & 0x3fffff]; \ - break; \ - case 1: /*16 bpp*/ \ - val = *(uint16_t *)&vram[addr & 0x3fffff]; \ - break; \ - case 2: /*24 bpp*/ \ - val = (*(uint32_t *)&vram[addr & 0x3fffff]) & 0xffffff; \ - break; \ - } \ - } while (0) - -#define Z_READ(addr) *(uint16_t *)&vram[addr & 0x3fffff] - -#define Z_WRITE(addr, val) if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) *(uint16_t *)&vram[addr & 0x3fffff] = val - -#define CLIP(x, y) \ - do \ - { \ - if ((virge->s3d.cmd_set & CMD_SET_HC) && \ - (x < virge->s3d.clip_l || \ - x > virge->s3d.clip_r || \ - y < virge->s3d.clip_t || \ - y > virge->s3d.clip_b)) \ - update = 0; \ - } while (0) - -#define CLIP_3D(x, y) \ - do \ - { \ - if ((s3d_tri->cmd_set & CMD_SET_HC) && \ - (x < s3d_tri->clip_l || \ - x > s3d_tri->clip_r || \ - y < s3d_tri->clip_t || \ - y > s3d_tri->clip_b)) \ - update = 0; \ - } while (0) - -#define Z_CLIP(Zzb, Zs) \ - do \ - { \ - if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ - switch ((s3d_tri->cmd_set >> 20) & 7) \ - { \ - case 0: update = 0; break; \ - case 1: if (Zs <= Zzb) update = 0; else Zzb = Zs; break; \ - case 2: if (Zs != Zzb) update = 0; else Zzb = Zs; break; \ - case 3: if (Zs < Zzb) update = 0; else Zzb = Zs; break; \ - case 4: if (Zs >= Zzb) update = 0; else Zzb = Zs; break; \ - case 5: if (Zs == Zzb) update = 0; else Zzb = Zs; break; \ - case 6: if (Zs > Zzb) update = 0; else Zzb = Zs; break; \ - case 7: update = 1; Zzb = Zs; break; \ - } \ - } while (0) - -#define MIX() \ - do \ - { \ - int c; \ - for (c = 0; c < 24; c++) \ - { \ - int d = (dest & (1 << c)) ? 1 : 0; \ - if (source & (1 << c)) d |= 2; \ - if (pattern & (1 << c)) d |= 4; \ - if (virge->s3d.rop & (1 << d)) out |= (1 << c); \ - } \ - } while (0) - -#define WRITE(addr, val) \ - do \ - { \ - switch (bpp) \ - { \ - case 0: /*8 bpp*/ \ - vram[addr & 0x3fffff] = val; \ - virge->svga.changedvram[(addr & 0x3fffff) >> 12] = changeframecount; \ - break; \ - case 1: /*16 bpp*/ \ - *(uint16_t *)&vram[addr & 0x3fffff] = val; \ - virge->svga.changedvram[(addr & 0x3fffff) >> 12] = changeframecount; \ - break; \ - case 2: /*24 bpp*/ \ - *(uint32_t *)&vram[addr & 0x3fffff] = (val & 0xffffff) | \ - (vram[(addr + 3) & 0x3fffff] << 24); \ - virge->svga.changedvram[(addr & 0x3fffff) >> 12] = changeframecount; \ - break; \ - } \ - } while (0) - -static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) -{ - uint8_t *vram = virge->svga.vram; - uint32_t mono_pattern[64]; - int count_mask; - int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; - int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; - int bpp; - int x_mul; - int cpu_dat_shift; - uint32_t *pattern_data; - uint32_t src_addr; - uint32_t dest_addr; - uint32_t source = 0, dest, pattern; - uint32_t out = 0; - int update; - - switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) - { - case CMD_SET_FORMAT_8: - bpp = 0; - x_mul = 1; - cpu_dat_shift = 8; - pattern_data = virge->s3d.pattern_8; - break; - case CMD_SET_FORMAT_16: - bpp = 1; - x_mul = 2; - cpu_dat_shift = 16; - pattern_data = virge->s3d.pattern_16; - break; - case CMD_SET_FORMAT_24: - default: - bpp = 2; - x_mul = 3; - cpu_dat_shift = 24; - pattern_data = virge->s3d.pattern_32; - break; - } - if (virge->s3d.cmd_set & CMD_SET_MP) - pattern_data = mono_pattern; - - switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) - { - case CMD_SET_ITA_BYTE: - count_mask = ~0x7; - break; - case CMD_SET_ITA_WORD: - count_mask = ~0xf; - break; - case CMD_SET_ITA_DWORD: - default: - count_mask = ~0x1f; - break; - } - if (virge->s3d.cmd_set & CMD_SET_MP) - { - int x, y; - for (y = 0; y < 4; y++) - { - for (x = 0; x < 8; x++) - { - if (virge->s3d.mono_pat_0 & (1 << (x + y*8))) - mono_pattern[y*8 + x] = virge->s3d.pat_fg_clr; - else - mono_pattern[y*8 + x] = virge->s3d.pat_bg_clr; - if (virge->s3d.mono_pat_1 & (1 << (x + y*8))) - mono_pattern[(y+4)*8 + x] = virge->s3d.pat_fg_clr; - else - mono_pattern[(y+4)*8 + x] = virge->s3d.pat_bg_clr; - } - } - } - switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK) - { - case CMD_SET_COMMAND_NOP: - break; - - case CMD_SET_COMMAND_BITBLT: - if (count == -1) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - virge->s3d.data_left_count = 0; - -/* pclog("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n", - virge->s3d.src_x, - virge->s3d.src_y, - virge->s3d.dest_x, - virge->s3d.dest_y, - virge->s3d.w, - virge->s3d.h, - virge->s3d.rop, - virge->s3d.src_base, - virge->s3d.dest_base);*/ - - if (virge->s3d.cmd_set & CMD_SET_IDS) - return; - } - if (!virge->s3d.h) - return; - while (count) - { - src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + (virge->s3d.src_y * virge->s3d.src_str); - dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - out = 0; - update = 1; - - switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) - { - case 0: - case CMD_SET_MS: - READ(src_addr, source); - if ((virge->s3d.cmd_set & CMD_SET_TP) && source == virge->s3d.src_fg_clr) - update = 0; - break; - case CMD_SET_IDS: - if (virge->s3d.data_left_count) - { - /*Handle shifting for 24-bit data*/ - source = virge->s3d.data_left; - source |= ((cpu_dat << virge->s3d.data_left_count) & ~0xff000000); - cpu_dat >>= (cpu_dat_shift - virge->s3d.data_left_count); - count -= (cpu_dat_shift - virge->s3d.data_left_count); - virge->s3d.data_left_count = 0; - if (count < cpu_dat_shift) - { - virge->s3d.data_left = cpu_dat; - virge->s3d.data_left_count = count; - count = 0; - } - } - else - { - source = cpu_dat; - cpu_dat >>= cpu_dat_shift; - count -= cpu_dat_shift; - if (count < cpu_dat_shift) - { - virge->s3d.data_left = cpu_dat; - virge->s3d.data_left_count = count; - count = 0; - } - } - if ((virge->s3d.cmd_set & CMD_SET_TP) && source == virge->s3d.src_fg_clr) - update = 0; - break; - case CMD_SET_IDS | CMD_SET_MS: - source = (cpu_dat & (1 << 31)) ? virge->s3d.src_fg_clr : virge->s3d.src_bg_clr; - if ((virge->s3d.cmd_set & CMD_SET_TP) && !(cpu_dat & (1 << 31))) - update = 0; - cpu_dat <<= 1; - count--; - break; - } - - CLIP(virge->s3d.dest_x, virge->s3d.dest_y); - - if (update) - { - READ(dest_addr, dest); - pattern = pattern_data[(virge->s3d.dest_y & 7)*8 + (virge->s3d.dest_x & 7)]; - MIX(); - - WRITE(dest_addr, out); - } - - virge->s3d.src_x += x_inc; - virge->s3d.src_x &= 0x7ff; - virge->s3d.dest_x += x_inc; - virge->s3d.dest_x &= 0x7ff; - if (!virge->s3d.w) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; - - virge->s3d.src_y += y_inc; - virge->s3d.dest_y += y_inc; - virge->s3d.h--; - - switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) - { - case CMD_SET_IDS: - cpu_dat >>= (count - (count & count_mask)); - count &= count_mask; - virge->s3d.data_left_count = 0; - break; - - case CMD_SET_IDS | CMD_SET_MS: - cpu_dat <<= (count - (count & count_mask)); - count &= count_mask; - break; - } - if (!virge->s3d.h) - { - return; - } - } - else - virge->s3d.w--; - } - break; - - case CMD_SET_COMMAND_RECTFILL: - /*No source, pattern = pat_fg_clr*/ - if (count == -1) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - -/* pclog("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, - virge->s3d.dest_y, - virge->s3d.w, - virge->s3d.h, - virge->s3d.rop, virge->s3d.dest_base);*/ - } - - while (count && virge->s3d.h) - { - uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - uint32_t source = 0, dest, pattern = virge->s3d.pat_fg_clr; - uint32_t out = 0; - int update = 1; - - CLIP(virge->s3d.dest_x, virge->s3d.dest_y); - - if (update) - { - READ(dest_addr, dest); - - MIX(); - - WRITE(dest_addr, out); - } - - virge->s3d.src_x += x_inc; - virge->s3d.src_x &= 0x7ff; - virge->s3d.dest_x += x_inc; - virge->s3d.dest_x &= 0x7ff; - if (!virge->s3d.w) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; - - virge->s3d.src_y += y_inc; - virge->s3d.dest_y += y_inc; - virge->s3d.h--; - if (!virge->s3d.h) - { - return; - } - } - else - virge->s3d.w--; - count--; - } - break; - - case CMD_SET_COMMAND_LINE: - if (count == -1) - { - virge->s3d.dest_x = virge->s3d.lxstart; - virge->s3d.dest_y = virge->s3d.lystart; - virge->s3d.h = virge->s3d.lycnt; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - } - while (virge->s3d.h) - { - int x; - int new_x; - int first_pixel = 1; - - x = virge->s3d.dest_x >> 20; - - if (virge->s3d.h == virge->s3d.lycnt && - ((virge->s3d.line_dir && x > virge->s3d.lxend0) || - (!virge->s3d.line_dir && x < virge->s3d.lxend0))) - x = virge->s3d.lxend0; - - if (virge->s3d.h == 1) - new_x = virge->s3d.lxend1 + (virge->s3d.line_dir ? 1 : -1); - else - new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20; - - - if ((virge->s3d.line_dir && x > new_x) || - (!virge->s3d.line_dir && x < new_x)) - goto skip_line; - - do - { - uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - uint32_t source = 0, dest, pattern; - uint32_t out = 0; - int update = 1; - - if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && - ((virge->s3d.line_dir && x < virge->s3d.lxend0) || - (!virge->s3d.line_dir && x > virge->s3d.lxend0))) - update = 0; - - if ((virge->s3d.h == 1 || !first_pixel) && - ((virge->s3d.line_dir && x > virge->s3d.lxend1) || - (!virge->s3d.line_dir && x < virge->s3d.lxend1))) - update = 0; - - CLIP(x, virge->s3d.dest_y); - - if (update) - { - READ(dest_addr, dest); - pattern = virge->s3d.pat_fg_clr; - - MIX(); - - WRITE(dest_addr, out); - } - - if (x < new_x) - x++; - else if (x > new_x) - x--; - first_pixel = 0; - } while (x != new_x); - -skip_line: - virge->s3d.dest_x += virge->s3d.ldx; - virge->s3d.dest_y--; - virge->s3d.h--; - } - break; - - case CMD_SET_COMMAND_POLY: - /*No source*/ - if (virge->s3d.pycnt & (1 << 28)) - virge->s3d.dest_r = virge->s3d.prxstart; - if (virge->s3d.pycnt & (1 << 29)) - virge->s3d.dest_l = virge->s3d.plxstart; - virge->s3d.h = virge->s3d.pycnt & 0x7ff; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - while (virge->s3d.h) - { - int x = virge->s3d.dest_l >> 20; - int xend = virge->s3d.dest_r >> 20; - int y = virge->s3d.pystart & 0x7ff; - int xdir = (x < xend) ? 1 : -1; - do - { - uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); - uint32_t source = 0, dest, pattern; - uint32_t out = 0; - int update = 1; - - CLIP(x, y); - - if (update) - { - READ(dest_addr, dest); - pattern = pattern_data[(y & 7)*8 + (x & 7)]; - MIX(); - - WRITE(dest_addr, out); - } - - x = (x + xdir) & 0x7ff; - } - while (x != (xend + xdir)); - - virge->s3d.dest_l += virge->s3d.pldx; - virge->s3d.dest_r += virge->s3d.prdx; - virge->s3d.h--; - virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; - } - break; - - default: - fatal("s3_virge_bitblt : blit command %i %08x\n", (virge->s3d.cmd_set >> 27) & 0xf, virge->s3d.cmd_set); - } -} - -#define RGB15_TO_24(val, r, g, b) b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \ - g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ - r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); - -#define RGB24_TO_24(val, r, g, b) b = val & 0xff; \ - g = (val & 0xff00) >> 8; \ - r = (val & 0xff0000) >> 16 - -#define RGB15(r, g, b, dest) \ - if (virge->dithering_enabled) \ - { \ - int add = dither[_y & 3][_x & 3]; \ - int _r = (r > 248) ? 248 : r+add; \ - int _g = (g > 248) ? 248 : g+add; \ - int _b = (b > 248) ? 248 : b+add; \ - dest = ((_b >> 3) & 0x1f) | (((_g >> 3) & 0x1f) << 5) | (((_r >> 3) & 0x1f) << 10); \ - } \ - else \ - dest = ((b >> 3) & 0x1f) | (((g >> 3) & 0x1f) << 5) | (((r >> 3) & 0x1f) << 10) - -#define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) - -typedef struct rgba_t -{ - int r, g, b, a; -} rgba_t; - -typedef struct s3d_state_t -{ - int32_t r, g, b, a, u, v, d, w; - - int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w; - - uint32_t base_z; - - uint32_t tbu, tbv; - - uint32_t cmd_set; - int max_d; - - uint16_t *texture[10]; - - uint32_t tex_bdr_clr; - - int32_t x1, x2; - int y; - - rgba_t dest_rgba; -} s3d_state_t; - -typedef struct s3d_texture_state_t -{ - int level; - int texture_shift; - - int32_t u, v; -} s3d_texture_state_t; - -static void (*tex_read)(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out); -static void (*tex_sample)(s3d_state_t *state); -static void (*dest_pixel)(s3d_state_t *state); - -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -static int _x, _y; - -static void tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; - - out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); - out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); - out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); - out->a = (val & 0x8000) ? 0xff : 0; -} - -static void tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; - - if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) - val = state->tex_bdr_clr; - - out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); - out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); - out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); - out->a = (val & 0x8000) ? 0xff : 0; -} - -static void tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; - - out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); - out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); - out->b = ((val & 0x000f) << 4) | (val & 0x000f); - out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); -} - -static void tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; - - if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) - val = state->tex_bdr_clr; - - out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); - out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); - out->b = ((val & 0x000f) << 4) | (val & 0x000f); - out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); -} - -static void tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; - - out->r = (val >> 16) & 0xff; - out->g = (val >> 8) & 0xff; - out->b = val & 0xff; - out->a = (val >> 24) & 0xff; -} -static void tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; - - if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) - val = state->tex_bdr_clr; - - out->r = (val >> 16) & 0xff; - out->g = (val >> 8) & 0xff; - out->b = val & 0xff; - out->a = (val >> 24) & 0xff; -} - -static void tex_sample_normal(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; - - tex_read(state, &texture_state, &state->dest_rgba); -} - -static void tex_sample_normal_filter(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[0]); - du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; - - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[1]); - - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); - - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); - - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; -} - -static void tex_sample_mipmap(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; - - tex_read(state, &texture_state, &state->dest_rgba); -} - -static void tex_sample_mipmap_filter(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[0]); - du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; - - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[1]); - - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); - - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); - - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; -} - -static void tex_sample_persp_normal(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - - tex_read(state, &texture_state, &state->dest_rgba); -} - -static void tex_sample_persp_normal_filter(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); - - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); - - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); - - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; -} - -static void tex_sample_persp_normal_375(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - - tex_read(state, &texture_state, &state->dest_rgba); -} - -static void tex_sample_persp_normal_filter_375(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); - - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); - - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); - - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; -} - - -static void tex_sample_persp_mipmap(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - - tex_read(state, &texture_state, &state->dest_rgba); -} - -static void tex_sample_persp_mipmap_filter(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); - - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); - - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); - - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; -} - -static void tex_sample_persp_mipmap_375(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - - tex_read(state, &texture_state, &state->dest_rgba); -} - -static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) -{ - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; - - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); - - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); - - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); - - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; -} - - -#define CLAMP(x) do \ - { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } \ - while (0) - -#define CLAMP_RGBA(r, g, b, a) \ - if ((r) & ~0xff) \ - r = ((r) < 0) ? 0 : 0xff; \ - if ((g) & ~0xff) \ - g = ((g) < 0) ? 0 : 0xff; \ - if ((b) & ~0xff) \ - b = ((b) < 0) ? 0 : 0xff; \ - if ((a) & ~0xff) \ - a = ((a) < 0) ? 0 : 0xff; - -#define CLAMP_RGB(r, g, b) do \ - { \ - if ((r) < 0) \ - r = 0; \ - if ((r) > 0xff) \ - r = 0xff; \ - if ((g) < 0) \ - g = 0; \ - if ((g) > 0xff) \ - g = 0xff; \ - if ((b) < 0) \ - b = 0; \ - if ((b) > 0xff) \ - b = 0xff; \ - } \ - while (0) - -static void dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) -{ - state->dest_rgba.r = state->r >> 7; - CLAMP(state->dest_rgba.r); - - state->dest_rgba.g = state->g >> 7; - CLAMP(state->dest_rgba.g); - - state->dest_rgba.b = state->b >> 7; - CLAMP(state->dest_rgba.b); - - state->dest_rgba.a = state->a >> 7; - CLAMP(state->dest_rgba.a); -} - -static void dest_pixel_unlit_texture_triangle(s3d_state_t *state) -{ - tex_sample(state); - - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a = state->a >> 7; -} - -static void dest_pixel_lit_texture_decal(s3d_state_t *state) -{ - tex_sample(state); - - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a = state->a >> 7; -} - -static void dest_pixel_lit_texture_reflection(s3d_state_t *state) -{ - tex_sample(state); - - state->dest_rgba.r += (state->r >> 7); - state->dest_rgba.g += (state->g >> 7); - state->dest_rgba.b += (state->b >> 7); - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a += (state->a >> 7); - - CLAMP_RGBA(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, state->dest_rgba.a); -} - -static void dest_pixel_lit_texture_modulate(s3d_state_t *state) -{ - int r = state->r >> 7, g = state->g >> 7, b = state->b >> 7, a = state->a >> 7; - - tex_sample(state); - - CLAMP_RGBA(r, g, b, a); - - state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8; - state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; - state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; - - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a = a; -} - -static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) -{ - uint8_t *vram = virge->svga.vram; - - int x_dir = s3d_tri->tlr ? 1 : -1; - - int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); - - int y_count = yc; - - int bpp = (s3d_tri->cmd_set >> 2) & 7; - - uint32_t dest_offset, z_offset; - - uint32_t src_col; - int src_r = 0, src_g = 0, src_b = 0; - - int x; - int xe; - uint32_t z; - - uint32_t dest_addr, z_addr; - int dx; - int x_offset; - int xz_offset; - - int update; - uint16_t src_z = 0; - - if (s3d_tri->cmd_set & CMD_SET_HC) - { - if (state->y < s3d_tri->clip_t) - return; - if (state->y > s3d_tri->clip_b) - { - int diff_y = state->y - s3d_tri->clip_b; - - if (diff_y > y_count) - diff_y = y_count; - - state->base_u += (s3d_tri->TdUdY * diff_y); - state->base_v += (s3d_tri->TdVdY * diff_y); - state->base_z += (s3d_tri->TdZdY * diff_y); - state->base_r += (s3d_tri->TdRdY * diff_y); - state->base_g += (s3d_tri->TdGdY * diff_y); - state->base_b += (s3d_tri->TdBdY * diff_y); - state->base_a += (s3d_tri->TdAdY * diff_y); - state->base_d += (s3d_tri->TdDdY * diff_y); - state->base_w += (s3d_tri->TdWdY * diff_y); - state->x1 += (dx1 * diff_y); - state->x2 += (dx2 * diff_y); - state->y -= diff_y; - dest_offset -= s3d_tri->dest_str; - z_offset -= s3d_tri->z_str; - y_count -= diff_y; - } - if ((state->y - y_count) < s3d_tri->clip_t) - y_count = state->y - s3d_tri->clip_t; - } - - dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); - z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); - - for (; y_count > 0; y_count--) - { - x = (state->x1 + ((1 << 20) - 1)) >> 20; - xe = (state->x2 + ((1 << 20) - 1)) >> 20; - z = (state->base_z > 0) ? (state->base_z << 1) : 0; - if (x_dir < 0) - { - x--; - xe--; - } - - if (((x != xe) && ((x_dir > 0) && (x < xe))) || ((x_dir < 0) && (x > xe))) - { - dx = (x_dir > 0) ? ((31 - ((state->x1-1) >> 15)) & 0x1f) : (((state->x1-1) >> 15) & 0x1f); - x_offset = x_dir * (bpp + 1); - xz_offset = x_dir << 1; - if (x_dir > 0) - dx += 1; - state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); - state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); - state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); - state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); - state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); - state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); - state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); - state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); - z += ((s3d_tri->TdZdX * dx) >> 5); - - if (s3d_tri->cmd_set & CMD_SET_HC) - { - if (x_dir > 0) - { - if (x > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - xe = s3d_tri->clip_r; - if (x < s3d_tri->clip_l) - { - int diff_x = s3d_tri->clip_l - x; - - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); - - x = s3d_tri->clip_l; - } - } - else - { - if (x < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - xe = s3d_tri->clip_l; - if (x > s3d_tri->clip_r) - { - int diff_x = x - s3d_tri->clip_r; - - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); - - x = s3d_tri->clip_r; - } - } - } - - virge->svga.changedvram[(dest_offset & 0x3fffff) >> 12] = changeframecount; - - dest_addr = dest_offset + (x * (bpp + 1)); - z_addr = z_offset + (x << 1); - - for (; x != xe; x = (x + x_dir) & 0xfff) - { - update = 1; - _x = x; _y = state->y; - - if (use_z) - { - src_z = Z_READ(z_addr); - Z_CLIP(src_z, z >> 16); - } - - if (update) - { - uint32_t dest_col; - - dest_pixel(state); - - if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) - { - switch (bpp) - { - case 0: /*8 bpp*/ - /*Not implemented yet*/ - break; - case 1: /*16 bpp*/ - src_col = *(uint16_t *)&vram[dest_addr & 0x3fffff]; - RGB15_TO_24(src_col, src_r, src_g, src_b); - break; - case 2: /*24 bpp*/ - src_col = (*(uint32_t *)&vram[dest_addr & 0x3fffff]) & 0xffffff; - RGB24_TO_24(src_col, src_r, src_g, src_b); - break; - } - - state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + (src_r * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + (src_g * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + (src_b * (255 - state->dest_rgba.a))) / 255; - } - - switch (bpp) - { - case 0: /*8 bpp*/ - /*Not implemented yet*/ - break; - case 1: /*16 bpp*/ - RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); - *(uint16_t *)&vram[dest_addr] = dest_col; - break; - case 2: /*24 bpp*/ - dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); - *(uint8_t *)&vram[dest_addr] = dest_col & 0xff; - *(uint8_t *)&vram[dest_addr + 1] = (dest_col >> 8) & 0xff; - *(uint8_t *)&vram[dest_addr + 2] = (dest_col >> 16) & 0xff; - break; - } - - if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) - Z_WRITE(z_addr, src_z); - } - - z += s3d_tri->TdZdX; - state->u += s3d_tri->TdUdX; - state->v += s3d_tri->TdVdX; - state->r += s3d_tri->TdRdX; - state->g += s3d_tri->TdGdX; - state->b += s3d_tri->TdBdX; - state->a += s3d_tri->TdAdX; - state->d += s3d_tri->TdDdX; - state->w += s3d_tri->TdWdX; - dest_addr += x_offset; - z_addr += xz_offset; - virge->pixel_count++; - } - } -tri_skip_line: - state->x1 += dx1; - state->x2 += dx2; - state->base_u += s3d_tri->TdUdY; - state->base_v += s3d_tri->TdVdY; - state->base_z += s3d_tri->TdZdY; - state->base_r += s3d_tri->TdRdY; - state->base_g += s3d_tri->TdGdY; - state->base_b += s3d_tri->TdBdY; - state->base_a += s3d_tri->TdAdY; - state->base_d += s3d_tri->TdDdY; - state->base_w += s3d_tri->TdWdY; - state->y--; - dest_offset -= s3d_tri->dest_str; - z_offset -= s3d_tri->z_str; - } -} - -static int tex_size[8] = -{ - 4*2, - 2*2, - 2*2, - 1*2, - 2/1, - 2/1, - 1*2, - 1*2 -}; - -static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) -{ - s3d_state_t state; - - uint32_t tex_base; - int c; - - uint64_t start_time = timer_read(); - uint64_t end_time; - - state.tbu = s3d_tri->tbu << 11; - state.tbv = s3d_tri->tbv << 11; - - state.max_d = (s3d_tri->cmd_set >> 8) & 15; - - state.tex_bdr_clr = s3d_tri->tex_bdr_clr; - - state.cmd_set = s3d_tri->cmd_set; - - state.base_u = s3d_tri->tus; - state.base_v = s3d_tri->tvs; - state.base_z = s3d_tri->tzs; - state.base_r = (int32_t)s3d_tri->trs; - state.base_g = (int32_t)s3d_tri->tgs; - state.base_b = (int32_t)s3d_tri->tbs; - state.base_a = (int32_t)s3d_tri->tas; - state.base_d = s3d_tri->tds; - state.base_w = s3d_tri->tws; - - tex_base = s3d_tri->tex_base; - for (c = 9; c >= 0; c--) - { - state.texture[c] = (uint16_t *)&virge->svga.vram[tex_base]; - if (c <= state.max_d) - tex_base += ((1 << (c*2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2; - } - - switch ((s3d_tri->cmd_set >> 27) & 0xf) - { - case 0: - dest_pixel = dest_pixel_gouraud_shaded_triangle; - break; - case 1: - case 5: - switch ((s3d_tri->cmd_set >> 15) & 0x3) - { - case 0: - dest_pixel = dest_pixel_lit_texture_reflection; - break; - case 1: - dest_pixel = dest_pixel_lit_texture_modulate; - break; - case 2: - dest_pixel = dest_pixel_lit_texture_decal; - break; - default: - pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); - return; - } - break; - case 2: - case 6: - dest_pixel = dest_pixel_unlit_texture_triangle; - break; - default: - pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); - return; - } - - switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0)) - { - case 0: case 1: - tex_sample = tex_sample_mipmap; - break; - case 2: case 3: - tex_sample = virge->bilinear_enabled ? tex_sample_mipmap_filter : tex_sample_mipmap; - break; - case 4: case 5: - tex_sample = tex_sample_normal; - break; - case 6: case 7: - tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal; - break; - case (0 | 8): case (1 | 8): - if (virge->is_375) - tex_sample = tex_sample_persp_mipmap_375; - else - tex_sample = tex_sample_persp_mipmap; - break; - case (2 | 8): case (3 | 8): - if (virge->is_375) - tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; - else - tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; - break; - case (4 | 8): case (5 | 8): - if (virge->is_375) - tex_sample = tex_sample_persp_normal_375; - else - tex_sample = tex_sample_persp_normal; - break; - case (6 | 8): case (7 | 8): - if (virge->is_375) - tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; - else - tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; - break; - } - - switch ((s3d_tri->cmd_set >> 5) & 7) - { - case 0: - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap; - break; - case 1: - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap; - break; - case 2: - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; - break; - default: - pclog("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; - break; - } - - state.y = s3d_tri->tys; - state.x1 = s3d_tri->txs; - state.x2 = s3d_tri->txend01; - tri(virge, s3d_tri, &state, s3d_tri->ty01, s3d_tri->TdXdY02, s3d_tri->TdXdY01); - state.x2 = s3d_tri->txend12; - tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12); - - virge->tri_count++; - - end_time = timer_read(); - - virge_time += end_time - start_time; -} - -static void render_thread(void *param) -{ - virge_t *virge = (virge_t *)param; - - while (1) - { - thread_wait_event(virge->wake_render_thread, -1); - thread_reset_event(virge->wake_render_thread); - virge->s3d_busy = 1; - while (!RB_EMPTY) - { - s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]); - virge->s3d_read_idx++; - - if (RB_ENTRIES == RB_SIZE - 1) - thread_set_event(virge->not_full_event); - } - virge->s3d_busy = 0; - virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); - } -} - -static void queue_triangle(virge_t *virge) -{ - if (RB_FULL) - { - thread_reset_event(virge->not_full_event); - if (RB_FULL) - thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/ - } - virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri; - virge->s3d_write_idx++; - if (!virge->s3d_busy) - thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/ -} - -static void s3_virge_hwcursor_draw(svga_t *svga, int displine) -{ - virge_t *virge = (virge_t *)svga->p; - int x; - uint16_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; - - 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]; - if (svga->crtc[0x55] & 0x10) - { - /*X11*/ - for (xx = 0; xx < 16; xx++) - { - if (offset >= svga->hwcursor_latch.x) - { - if (dat[0] & 0x8000) - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = virge->hwcursor_col[dat[1] >> 15]; - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - } - else - { - /*Windows*/ - for (xx = 0; xx < 16; xx++) - { - if (offset >= svga->hwcursor_latch.x) - { - if (!(dat[0] & 0x8000)) - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = virge->hwcursor_col[dat[1] >> 15]; - else if (dat[1] & 0x8000) - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - } - svga->hwcursor_latch.addr += 4; - } - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; -} - -#define DECODE_YCbCr() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t Cr, Cb; \ - int dR, dG, dB; \ - \ - y1 = src[0]; \ - Cr = src[1] - 0x80; \ - y2 = src[2]; \ - Cb = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359*Cr) >> 8; \ - dG = (88*Cb + 183*Cr) >> 8; \ - dB = (453*Cb) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) - -/*Both YUV formats are untested*/ -#define DECODE_YUV211() \ - do \ - { \ - uint8_t y1, y2, y3, y4; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - y2 = (298 * (src[2] - 16)) >> 8; \ - V = src[3] - 0x80; \ - y3 = (298 * (src[4] - 16)) >> 8; \ - y4 = (298 * (src[5] - 16)) >> 8; \ - src += 6; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - r[x_write+2] = y3 + dR; \ - CLAMP(r[x_write+2]); \ - g[x_write+2] = y3 - dG; \ - CLAMP(g[x_write+2]); \ - b[x_write+2] = y3 + dB; \ - CLAMP(b[x_write+2]); \ - \ - r[x_write+3] = y4 + dR; \ - CLAMP(r[x_write+3]); \ - g[x_write+3] = y4 - dG; \ - CLAMP(g[x_write+3]); \ - b[x_write+3] = y4 + dB; \ - CLAMP(b[x_write+3]); \ - \ - x_write = (x_write + 4) & 7; \ - } while (0) - -#define DECODE_YUV422() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - V = src[2] - 0x80; \ - y2 = (298 * (src[3] - 16)) >> 8; \ - src += 4; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) - -#define DECODE_RGB555() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ - b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) - -#define DECODE_RGB565() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ - b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) - -#define DECODE_RGB888() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 3; \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) - -#define DECODE_XRGB8888() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 4; \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) - -#define OVERLAY_SAMPLE() \ - do \ - { \ - switch (virge->streams.sdif) \ - { \ - case 1: \ - DECODE_YCbCr(); \ - break; \ - case 2: \ - DECODE_YUV422(); \ - break; \ - case 3: \ - DECODE_RGB555(); \ - break; \ - case 4: \ - DECODE_YUV211(); \ - break; \ - case 5: \ - DECODE_RGB565(); \ - break; \ - case 6: \ - DECODE_RGB888(); \ - break; \ - case 7: \ - default: \ - DECODE_XRGB8888(); \ - break; \ - } \ - } while (0) - -static void s3_virge_overlay_draw(svga_t *svga, int displine) -{ - virge_t *virge = (virge_t *)svga->p; - int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1; - int h_acc = virge->streams.dda_horiz_accumulator; - int r[8], g[8], b[8]; - int x_size, x_read = 4, x_write = 4; - int x; - uint32_t *p; - uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - int y_add = enable_overscan ? 16 : 0; - int x_add = enable_overscan ? 8 : 0; - - p = &((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add]; - - if ((offset + virge->streams.sec_w) > virge->streams.pri_w) - x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; - else - x_size = virge->streams.sec_w + 1; - - OVERLAY_SAMPLE(); - - for (x = 0; x < x_size; x++) - { - *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); - - h_acc += virge->streams.k1_horiz_scale; - if (h_acc >= 0) - { - if ((x_read ^ (x_read + 1)) & ~3) - OVERLAY_SAMPLE(); - x_read = (x_read + 1) & 7; - - h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale); - } - } - - svga->overlay_latch.v_acc += virge->streams.k1_vert_scale; - if (svga->overlay_latch.v_acc >= 0) - { - svga->overlay_latch.v_acc += (virge->streams.k2_vert_scale - virge->streams.k1_vert_scale); - svga->overlay_latch.addr += virge->streams.sec_stride; - } -} - -static uint8_t s3_virge_pci_read(int func, int addr, void *p) -{ - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - uint8_t ret = 0; - switch (addr) - { - case 0x00: ret = 0x33; break; /*'S3'*/ - case 0x01: ret = 0x53; break; - - case 0x02: ret = virge->virge_id_low; break; - case 0x03: ret = virge->virge_id_high; break; - - case 0x04: ret = virge->pci_regs[0x04] & 0x27; break; - - case 0x07: ret = virge->pci_regs[0x07] & 0x36; break; - - case 0x08: ret = 0; break; /*Revision ID*/ - case 0x09: ret = 0; break; /*Programming interface*/ - - case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ - case 0x0b: ret = 0x03; /*output = 3; */break; - - case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break; - - case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ - case 0x11: ret = 0x00; break; - case 0x12: ret = 0x00; break; - case 0x13: ret = svga->crtc[0x59] & 0xfc; break; - - case 0x30: ret = virge->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ - case 0x31: ret = 0x00; break; - case 0x32: ret = virge->pci_regs[0x32]; break; - case 0x33: ret = virge->pci_regs[0x33]; break; - - case 0x3c: ret = virge->pci_regs[0x3c]; break; - - case 0x3d: ret = 0x01; break; /*INTA*/ - - case 0x3e: ret = 0x04; break; - case 0x3f: ret = 0xff; break; - - } - return ret; -} - -static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x3d: case 0x3e: case 0x3f: - return; - - case PCI_REG_COMMAND: - if (val & PCI_COMMAND_IO) - { - io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - } - else - io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; - s3_virge_updatemapping(virge); - return; - case 0x07: - virge->pci_regs[0x07] = val & 0x3e; - return; - case 0x0d: - virge->pci_regs[0x0d] = val & 0xf8; - return; - - case 0x13: - svga->crtc[0x59] = val & 0xfc; - s3_virge_updatemapping(virge); - return; - - case 0x30: case 0x32: case 0x33: - virge->pci_regs[addr] = val; - if (virge->pci_regs[0x30] & 0x01) - { - uint32_t addr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); - mem_mapping_set_addr(&virge->bios_rom.mapping, addr, 0x8000); - mem_mapping_enable(&virge->bios_rom.mapping); - } - else - { - mem_mapping_disable(&virge->bios_rom.mapping); - } - return; - case 0x3c: - virge->pci_regs[0x3c] = val; - return; - } -} - -static void *s3_virge_init() -{ - virge_t *virge = malloc(sizeof(virge_t)); - memset(virge, 0, sizeof(virge_t)); - - virge->bilinear_enabled = device_get_config_int("bilinear"); - virge->dithering_enabled = device_get_config_int("dithering"); - virge->memory_size = device_get_config_int("memory"); - - svga_init(&virge->svga, virge, virge->memory_size << 20, - s3_virge_recalctimings, - s3_virge_in, s3_virge_out, - s3_virge_hwcursor_draw, - s3_virge_overlay_draw); - virge->svga.vblank_start = s3_virge_vblank_start; - - rom_init(&virge->bios_rom, L"roms/video/s3virge/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) - mem_mapping_disable(&virge->bios_rom.mapping); - - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, - svga_readw_linear, - svga_readl_linear, - svga_write_linear, - svga_writew_linear, - svga_writel_linear, - NULL, - 0, - &virge->svga); - - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - - virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; - virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; - - virge->virge_id_high = 0x56; - virge->virge_id_low = 0x31; - virge->virge_rev = 0; - virge->virge_id = 0xe1; - - switch (virge->memory_size) - { - case 2: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 4: - default: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; - } - - virge->svga.crtc[0x37] = 1; - virge->svga.crtc[0x53] = 1 << 3; - virge->svga.crtc[0x59] = 0x70; - - virge->is_375 = 0; - - virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); - - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); - - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); - - return virge; -} - -static void *s3_virge_988_init() -{ - virge_t *virge = malloc(sizeof(virge_t)); - memset(virge, 0, sizeof(virge_t)); - - virge->bilinear_enabled = device_get_config_int("bilinear"); - virge->dithering_enabled = device_get_config_int("dithering"); - virge->memory_size = device_get_config_int("memory"); - - svga_init(&virge->svga, virge, virge->memory_size << 20, - s3_virge_recalctimings, - s3_virge_in, s3_virge_out, - s3_virge_hwcursor_draw, - s3_virge_overlay_draw); - - rom_init(&virge->bios_rom, L"roms/video/s3virge/diamondstealth3000.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) - mem_mapping_disable(&virge->bios_rom.mapping); - - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, - svga_readw_linear, - svga_readl_linear, - svga_write_linear, - svga_writew_linear, - svga_writel_linear, - NULL, - 0, - &virge->svga); - - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - - virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; - virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; - - virge->virge_id_high = 0x88; - virge->virge_id_low = 0x3d; - virge->virge_rev = 0; - virge->virge_id = 0xe1; - - switch (virge->memory_size) - { - case 2: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 4: - default: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; - } - - virge->svga.crtc[0x37] = 1; - virge->svga.crtc[0x53] = 1 << 3; - virge->svga.crtc[0x59] = 0x70; - - virge->is_375 = 0; - - virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); - - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); - - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); - - return virge; -} - -static void *s3_virge_375_init(wchar_t *romfn) -{ - virge_t *virge = malloc(sizeof(virge_t)); - memset(virge, 0, sizeof(virge_t)); - - virge->bilinear_enabled = device_get_config_int("bilinear"); - virge->dithering_enabled = device_get_config_int("dithering"); - virge->memory_size = device_get_config_int("memory"); - - svga_init(&virge->svga, virge, virge->memory_size << 20, - s3_virge_recalctimings, - s3_virge_in, s3_virge_out, - s3_virge_hwcursor_draw, - s3_virge_overlay_draw); - - rom_init(&virge->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) - mem_mapping_disable(&virge->bios_rom.mapping); - - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, - svga_readw_linear, - svga_readl_linear, - svga_write_linear, - svga_writew_linear, - svga_writel_linear, - NULL, - 0, - &virge->svga); - - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - - virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; - virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; - - virge->virge_id_high = 0x8a; - virge->virge_id_low = 0x01; - virge->virge_rev = 0; - virge->virge_id = 0xe1; - - switch (virge->memory_size) - { - case 2: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 4: - default: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; - } - virge->svga.crtc[0x37] = 1; - virge->svga.crtc[0x53] = 1 << 3; - virge->svga.crtc[0x59] = 0x70; - - virge->svga.crtc[0x6c] = 0x01; - - virge->is_375 = 1; - - virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); - - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); - - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); - - return virge; -} - -static void *s3_virge_375_1_init() -{ - return s3_virge_375_init(L"roms/video/s3virge/86c375_1.bin"); -} - -static void *s3_virge_375_4_init() -{ - return s3_virge_375_init(L"roms/video/s3virge/86c375_4.bin"); -} - -static void s3_virge_close(void *p) -{ - virge_t *virge = (virge_t *)p; -#if 0 - FILE *f = fopen("vram.dmp", "wb"); - fwrite(virge->svga.vram, 4 << 20, 1, f); - fclose(f); -#endif - - thread_kill(virge->render_thread); - thread_destroy_event(virge->not_full_event); - thread_destroy_event(virge->wake_main_thread); - thread_destroy_event(virge->wake_render_thread); - - thread_kill(virge->fifo_thread); - thread_destroy_event(virge->wake_fifo_thread); - thread_destroy_event(virge->fifo_not_full_event); - - svga_close(&virge->svga); - - free(virge); -} - -static int s3_virge_available() -{ - return rom_present(L"roms/video/s3virge/s3virge.bin"); -} - -static int s3_virge_988_available() -{ - return rom_present(L"roms/video/s3virge/diamondstealth3000.VBI"); -} - -static int s3_virge_375_1_available() -{ - return rom_present(L"roms/video/s3virge/86c375_1.bin"); -} - -static int s3_virge_375_4_available() -{ - return rom_present(L"roms/video/s3virge/86c375_4.bin"); -} - -static void s3_virge_speed_changed(void *p) -{ - virge_t *virge = (virge_t *)p; - - svga_recalctimings(&virge->svga); -} - -static void s3_virge_force_redraw(void *p) -{ - virge_t *virge = (virge_t *)p; - - virge->svga.fullchange = changeframecount; -} - -static void s3_virge_add_status_info(char *s, int max_len, void *p) -{ - virge_t *virge = (virge_t *)p; - char temps[256]; - uint64_t new_time = timer_read(); - uint64_t status_diff = new_time - status_time; - status_time = new_time; - - if (!status_diff) - status_diff = 1; - - svga_add_status_info(s, max_len, &virge->svga); - sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes %i reads\n\n", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes, reg_reads); - strncat(s, temps, max_len); - - virge->pixel_count = virge->tri_count = 0; - virge_time = 0; - reg_reads = 0; - reg_writes = 0; -} - -static device_config_t s3_virge_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, - { - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "bilinear", "Bilinear filtering", CONFIG_BINARY, "", 1 - }, - { - "dithering", "Dithering", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } -}; - -device_t s3_virge_device = -{ - "Diamond Stealth 3D 2000 (S3 ViRGE)", - 0, - s3_virge_init, - s3_virge_close, - s3_virge_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config -}; - -device_t s3_virge_988_device = -{ - "Diamond Stealth 3D 3000 (S3 ViRGE/VX)", - 0, - s3_virge_988_init, - s3_virge_close, - s3_virge_988_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config -}; - -device_t s3_virge_375_device = -{ - "S3 ViRGE/DX", - 0, - s3_virge_375_1_init, - s3_virge_close, - s3_virge_375_1_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config -}; - -device_t s3_virge_375_4_device = -{ - "S3 ViRGE/DX (VBE 2.0)", - 0, - s3_virge_375_4_init, - s3_virge_close, - s3_virge_375_4_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config -}; From d3adc13445caafa037d1dac05c1585697562f247 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Thu, 27 Jul 2017 14:48:43 -0500 Subject: [PATCH 49/82] Ready experimental branch for remerging into master --- src/Makefile.mingw | 12 +++++++++--- src/Makefile.mingw64 | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 00889f507..d63c46706 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -22,7 +22,7 @@ endif # Various compile-time options. # -DROM_TRACE=0xcd800 traces ROM access from segment C800 # -DIO_TACE=0x66 traces I/O on port 0x66 -STUFF = -DDEV_BRANCH +STUFF = # Add feature selections here. # -DANSI_CFG forces the config file to ANSI encoding. @@ -52,6 +52,9 @@ endif ifndef USB USB = n endif +ifndef DEV_BRANCH +DEV_BRANCH = n +endif ifndef X64 X64 = n endif @@ -223,7 +226,6 @@ VIDOBJ = video.o \ vid_genius.o \ vid_s3.o vid_s3_virge.o \ vid_et4000.o vid_et4000w32.o vid_icd2061.o \ - vid_nv_riva128.o \ vid_oti067.o \ vid_paradise.o \ vid_tvga.o vid_tgui9440.o vid_tkd8001_ramdac.o \ @@ -247,8 +249,12 @@ WINOBJ = win.o \ win_iodev.o win_joystick.o win_midi.o \ win_settings.o win_deviceconfig.o win_joystickconfig.o \ 86Box.res +ifdef DEV_BRANCH +DEVOBJ = vid_nv_riva128.o +endif OBJ = $(MAINOBJ) $(CPUOBJ) $(SYSOBJ) $(DEVOBJ) $(USBOBJ) \ - $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) $(WINOBJ) + $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) $(WINOBJ) \ + $(DEVOBJ) LZFOBJ = lzf_c.o lzf_d.o diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index 2f0f9b408..53efdd58b 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -28,6 +28,6 @@ EXTRAS = DEBUG = n OPTIM = n X64 = y - +DEV_BRANCH = n # End of Makefile.mingw64. From 8607d10ef1a9031ae3adc0e295ba6ba9f39d9900 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Thu, 27 Jul 2017 14:55:47 -0500 Subject: [PATCH 50/82] Fix build --- src/Makefile.mingw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index d63c46706..e0d4340b4 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -250,11 +250,11 @@ WINOBJ = win.o \ win_settings.o win_deviceconfig.o win_joystickconfig.o \ 86Box.res ifdef DEV_BRANCH -DEVOBJ = vid_nv_riva128.o +DEVBRANCHOBJ = vid_nv_riva128.o endif OBJ = $(MAINOBJ) $(CPUOBJ) $(SYSOBJ) $(DEVOBJ) $(USBOBJ) \ $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) $(WINOBJ) \ - $(DEVOBJ) + $(DEVBRANCHOBJ) LZFOBJ = lzf_c.o lzf_d.o From 8bf4ff71c11481dc241024b5320c50fa67fff0f5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 27 Jul 2017 22:24:33 +0200 Subject: [PATCH 51/82] Fixed remaining crashes of the ViRGE that were due to my previous fix. --- src/VIDEO/vid_s3_virge.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/VIDEO/vid_s3_virge.c b/src/VIDEO/vid_s3_virge.c index 997b707e4..c903fe0a6 100644 --- a/src/VIDEO/vid_s3_virge.c +++ b/src/VIDEO/vid_s3_virge.c @@ -1350,18 +1350,27 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) svga_t *svga = &virge->svga; reg_writes++; - pclog("Write Address %x\n", addr & 0xe000); - if ((addr & 0xfffc) < 0x8000) { + if ((addr & 0xe000) == 0) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); + } + else + { s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); + } } else switch (addr & 0xfffc) { case 0: - s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); - svga_recalctimings(svga); - svga->fullchange = changeframecount; + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); break; case 0x8180: From 474838be8702ae307e91f6937ac635a8225e2991 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Jul 2017 23:59:40 +0200 Subject: [PATCH 52/82] Made sure the BPB is actually ignored when the drive is so configured; Fixed the S3 ViRGE warnings. --- src/VIDEO/vid_s3_virge.c | 8 ++++---- src/disc_img.c | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/VIDEO/vid_s3_virge.c b/src/VIDEO/vid_s3_virge.c index c903fe0a6..c61a672ca 100644 --- a/src/VIDEO/vid_s3_virge.c +++ b/src/VIDEO/vid_s3_virge.c @@ -1892,7 +1892,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) uint32_t *pattern_data; uint32_t src_addr; uint32_t dest_addr; - uint32_t source = 0, dest, pattern; + uint32_t source = 0, dest = 0, pattern; uint32_t out = 0; int update; @@ -2110,7 +2110,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) while (count && virge->s3d.h) { uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - uint32_t source = 0, dest, pattern = virge->s3d.pat_fg_clr; + uint32_t source = 0, dest = 0, pattern = virge->s3d.pat_fg_clr; uint32_t out = 0; int update = 1; @@ -2183,7 +2183,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) do { uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - uint32_t source = 0, dest, pattern; + uint32_t source = 0, dest = 0, pattern; uint32_t out = 0; int update = 1; @@ -2240,7 +2240,7 @@ skip_line: do { uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); - uint32_t source = 0, dest, pattern; + uint32_t source = 0, dest = 0, pattern; uint32_t out = 0; int update = 1; diff --git a/src/disc_img.c b/src/disc_img.c index 64eb40fe7..9d90946a6 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -35,7 +35,6 @@ static struct uint8_t sector_size; int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */ int dmf; - int hole; int track; int track_width; uint32_t base; @@ -341,6 +340,7 @@ void img_load(int drive, wchar_t *fn) uint8_t *bpos; uint16_t track_bytes = 0; uint8_t *literal; + int guess = 0; ext = get_extension_w(fn); @@ -706,11 +706,17 @@ jump_if_fdf: img[drive].sides = 2; img[drive].sector_size = 2; - img[drive].hole = 0; - pclog("BPB reports %i sides and %i bytes per sector (%i sectors total)\n", bpb_sides, bpb_bps, bpb_total); - if ((((bpb_sides < 1) || (bpb_sides > 2) || !bps_is_valid(bpb_bps) || !first_byte_is_valid(first_byte)) && !fdi && !cqm) || !fdd_get_check_bpb(drive)) + guess = (bpb_sides < 1); + guess = guess || (bpb_sides > 2); + guess = guess || !bps_is_valid(bpb_bps); + guess = guess || !first_byte_is_valid(first_byte); + guess = guess || !fdd_get_check_bpb(drive); + guess = guess && !fdi; + guess = guess && !cqm; + + if (guess) { /* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably not a BPB at all, so we have to guess the parameters from file size. */ @@ -756,6 +762,10 @@ jump_if_fdf: memset(discfns[drive], 0, sizeof(discfns[drive])); return; } + + bpb_sides = img[drive].sides; + bpb_sectors = img[drive].sectors; + bpb_total = size >> (img[drive].sector_size + 7); } else { From f43334283b015a4b07bcaede35fbf85f967db305 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Jul 2017 01:20:17 +0200 Subject: [PATCH 53/82] Fixed a small recompiler mistake - Windows XP now works again on the recompiler. --- src/CPU/codegen_x86-64.c | 2 +- src/CPU/codegen_x86.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CPU/codegen_x86-64.c b/src/CPU/codegen_x86-64.c index d174f8f48..6a3e714f1 100644 --- a/src/CPU/codegen_x86-64.c +++ b/src/CPU/codegen_x86-64.c @@ -1099,7 +1099,7 @@ generate_call: } } - if ((op_table == x86_opcodes_REPNE || op_table == x86_opcodes_REPE) && !op_table[opcode | op_32]) + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { op_table = x86_dynarec_opcodes; recomp_op_table = recomp_opcodes; diff --git a/src/CPU/codegen_x86.c b/src/CPU/codegen_x86.c index cf5492040..80bc3dbcf 100644 --- a/src/CPU/codegen_x86.c +++ b/src/CPU/codegen_x86.c @@ -2039,7 +2039,7 @@ generate_call: #endif } - if ((op_table == x86_opcodes_REPNE || op_table == x86_opcodes_REPE) && !op_table[opcode | op_32]) + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { op_table = x86_dynarec_opcodes; recomp_op_table = recomp_opcodes; From c28eda27138cdbf6462316b0d8225d8c36c9c682 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Jul 2017 02:36:49 +0200 Subject: [PATCH 54/82] Bus mouse now returns button status in READ_X_LOW as well, fixes bus mouse in AMI WinBIOS 486 CMOS Setup. --- src/mouse_bus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mouse_bus.c b/src/mouse_bus.c index 5d20f2f31..ea315dd0d 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -155,7 +155,8 @@ static uint8_t busmouse_read(uint16_t port, void *priv) switch (busmouse->control_val & 0x60) { case READ_X_LOW: - r = busmouse->x & 0x0f; + /* r = busmouse->x & 0x0f; */ + r = ((busmouse->but ^ 7) << 5) | (busmouse->x & 0x0f); break; case READ_X_HIGH: From f1053d4710d8e02edc5ff604059dd4d479b178a4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Jul 2017 11:14:46 +0200 Subject: [PATCH 55/82] Applied the two mainline PCem commit relating to GUS and 16-bit DMA. --- src/SOUND/snd_gus.c | 44 +++++++++++++++++++++++++++++++++++--------- src/dma.c | 3 ++- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/SOUND/snd_gus.c b/src/SOUND/snd_gus.c index bf625dfb2..837f3bfc1 100644 --- a/src/SOUND/snd_gus.c +++ b/src/SOUND/snd_gus.c @@ -341,13 +341,27 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); while (c<65536) { int dma_result; - d = gus->ram[gus->dmaaddr]; - if (val & 0x80) d ^= 0x80; - dma_result = dma_channel_write(gus->dma, d); - if (dma_result == DMA_NODATA) - break; + if (val & 0x04) + { + uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1); + d = gus->ram[gus_addr] | (gus->ram[gus_addr + 1] << 8); + if (val & 0x80) + d ^= 0x8080; + dma_result = dma_channel_write(gus->dma, d); + if (dma_result == DMA_NODATA) + break; + } + else + { + d = gus->ram[gus->dmaaddr]; + if (val & 0x80) + d ^= 0x80; + dma_result = dma_channel_write(gus->dma, d); + if (dma_result == DMA_NODATA) + break; + } gus->dmaaddr++; - gus->dmaaddr&=0xFFFFF; + gus->dmaaddr &= 0xFFFFF; c++; if (dma_result & DMA_OVER) break; @@ -363,10 +377,22 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); d = dma_channel_read(gus->dma); if (d == DMA_NODATA) break; - if (val&0x80) d^=0x80; - gus->ram[gus->dmaaddr]=d; + if (val & 0x04) + { + uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1); + if (val & 0x80) + d ^= 0x8080; + gus->ram[gus_addr] = d & 0xff; + gus->ram[gus_addr +1] = (d >> 8) & 0xff; + } + else + { + if (val & 0x80) + d ^= 0x80; + gus->ram[gus->dmaaddr] = d; + } gus->dmaaddr++; - gus->dmaaddr&=0xFFFFF; + gus->dmaaddr &= 0xFFFFF; c++; if (d & DMA_OVER) break; diff --git a/src/dma.c b/src/dma.c index 96f98bd96..ae95ffafa 100644 --- a/src/dma.c +++ b/src/dma.c @@ -705,11 +705,12 @@ int dma_channel_write(int channel, uint16_t val) dma16.cc[channel] = dma16.cb[channel] + 1; dma16.ac[channel] = dma16.ab[channel]; } + else dma16.m |= (1 << channel); dma16.stat |= (1 << channel); } - if (dma.m & (1 << channel)) + if (dma16.m & (1 << channel)) return DMA_OVER; } return 0; From 853ab999b759ec98623e4cb8c96ab8163ae04ad6 Mon Sep 17 00:00:00 2001 From: waltje Date: Sun, 30 Jul 2017 17:09:56 -0400 Subject: [PATCH 56/82] Fixed SCSI DISK for wrong length, hopefully fixes crash. --- src/scsi_disk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scsi_disk.c b/src/scsi_disk.c index 340ffd6b3..a3b8c7dda 100644 --- a/src/scsi_disk.c +++ b/src/scsi_disk.c @@ -6,7 +6,7 @@ * * Emulation of SCSI fixed and removable disks. * - * Version: @(#)scsi_disk.c 1.0.2 2017/06/16 + * Version: @(#)scsi_disk.c 1.0.3 2017/07/30 * * Author: Miran Grca, * Copyright 2017-2017 Miran Grca. @@ -772,7 +772,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) break; case GPCMD_MECHANISM_STATUS: - len = (hdbufferb[7] << 16) | (hdbufferb[8] << 8) | hdbufferb[9]; + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; memset(hdbufferb, 0, 8); hdbufferb[5] = 1; From 49c4168f5b35077da9531968c94169ce1dde03db Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sun, 30 Jul 2017 23:21:11 -0500 Subject: [PATCH 57/82] Fixup --- src/Makefile.mingw | 3 +++ src/VIDEO/vid_nv_riva128.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index e0d4340b4..328fc2c76 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -131,6 +131,9 @@ else PLATCG = codegen_x86.o endif +ifeq ($(DEV_BRANCH), y) +CFLAGS += -DDEV_BRANCH +endif ifeq ($(WALTJE), y) OPENDIR = win_opendir.o diff --git a/src/VIDEO/vid_nv_riva128.c b/src/VIDEO/vid_nv_riva128.c index 1bb638e50..d43b9e114 100644 --- a/src/VIDEO/vid_nv_riva128.c +++ b/src/VIDEO/vid_nv_riva128.c @@ -2200,7 +2200,7 @@ void rivatnt_pgraph_ctx_switch(void *p) ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2); break; case 0x28: - ret = svga->crtc[0x28] & 3; + ret = svga->crtc[0x28] & 0x3f; break; default: ret = svga->crtc[svga->crtcreg]; From 374943f4f5413d44e94d6af132a108431be712c6 Mon Sep 17 00:00:00 2001 From: waltje Date: Thu, 3 Aug 2017 14:07:03 -0400 Subject: [PATCH 58/82] Mouse cleanups. Serial unmodified, but working on DOS,WfW,Win2000,XP for serial mice. --- src/Makefile.mingw | 13 +- src/model.c | 3 +- src/mouse.c | 17 +-- src/mouse.h | 42 ++++-- src/mouse_bus.c | 17 +-- src/mouse_bus.h | 30 ---- src/mouse_ps2.c | 9 +- src/mouse_ps2.h | 4 - src/mouse_serial.c | 359 +++++++++++++-------------------------------- src/mouse_serial.h | 30 ---- src/scsi.h | 4 + src/scsi_aha154x.c | 14 +- src/serial.c | 47 +++--- 13 files changed, 199 insertions(+), 390 deletions(-) delete mode 100644 src/mouse_bus.h delete mode 100644 src/mouse_ps2.h delete mode 100644 src/mouse_serial.h diff --git a/src/Makefile.mingw b/src/Makefile.mingw index e0d4340b4..ef0636e31 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -8,7 +8,7 @@ # # Modified Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.31 2017/06/19 +# Version: @(#)Makefile.mingw 1.0.32 2017/07/27 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -455,7 +455,7 @@ mfm_at.o: ibm.h device.h hdd_image.h io.h pic.h timer.h mfm_at.h mfm_xebec.o: ibm.h device.h dma.h hdd_image.h io.h mem.h pic.h rom.h timer.h mfm_xebec.h model.o: ibm.h io.h mem.h rom.h device.h model.h cpu/cpu.h \ - mouse.h mouse_ps2.h cdrom.h disc.h dma.h fdc.h \ + mouse.h cdrom.h disc.h dma.h fdc.h \ fdc37c665.h fdc37c669.h fdc37c932fr.h \ gameport.h i82335.h ide.h intel.h intel_flash.h \ keyboard_amstrad.h keyboard_at.h keyboard_olim24.h \ @@ -466,14 +466,13 @@ model.o: ibm.h io.h mem.h rom.h device.h model.h cpu/cpu.h \ video/vid_pcjr.h video/vid_tandy.h w83877f.h wd76c10.h \ xtide.h bugger.h -mouse.o: ibm.h cpu/cpu.h device.h model.h \ - mouse.h mouse_serial.h mouse_ps2.h mouse_bus.h keyboard_olim24.h +mouse.o: ibm.h cpu/cpu.h device.h model.h mouse.h keyboard_olim24.h -mouse_bus.o: ibm.h io.h pic.h mouse.h mouse_bus.h plat_mouse.h +mouse_bus.o: ibm.h io.h pic.h mouse.h -mouse_ps2.o: ibm.h keyboard_at.h mouse.h mouse_ps2.h plat_mouse.h +mouse_ps2.o: ibm.h keyboard_at.h mouse.h plat_mouse.h -mouse_serial.o: ibm.h timer.h serial.h mouse.h mouse_serial.h +mouse_serial.o: ibm.h timer.h serial.h mouse.h neat.o: ibm.h cpu/cpu.h io.h device.h model.h diff --git a/src/model.c b/src/model.c index e37fae1db..018d7fe05 100644 --- a/src/model.c +++ b/src/model.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)model.c 1.0.4 2017/06/21 + * Version: @(#)model.c 1.0.5 2017/07/27 * * Authors: Sarah Walker, * Miran Grca, @@ -26,7 +26,6 @@ #include "device.h" #include "model.h" #include "mouse.h" -#include "mouse_ps2.h" #include "cdrom.h" #include "disc.h" diff --git a/src/mouse.c b/src/mouse.c index a72030324..4a2d53f0b 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -8,7 +8,7 @@ * * Common driver module for MOUSE devices. * - * Version: @(#)mouse.c 1.0.4 2017/07/24 + * Version: @(#)mouse.c 1.0.5 2017/07/27 * * Authors: Sarah Walker, * Miran Grca, @@ -21,9 +21,6 @@ #include "cpu/cpu.h" #include "device.h" #include "mouse.h" -#include "mouse_serial.h" -#include "mouse_ps2.h" -#include "mouse_bus.h" #include "model.h" @@ -36,18 +33,18 @@ static mouse_t mouse_none = { static mouse_t *mouse_list[] = { &mouse_none, - &mouse_bus, /* 1 Microsoft/Logitech Bus Mouse 2-button */ - &mouse_inport, /* 2 Microsoft InPort Mouse */ - &mouse_msystems, /* 3 Mouse Systems */ + &mouse_bus_logitech, /* 1 Logitech Bus Mouse 2-button */ + &mouse_bus_msinport, /* 2 Microsoft InPort Mouse */ + &mouse_serial_msystems, /* 3 Mouse Systems Serial Mouse */ &mouse_serial_microsoft, /* 4 Microsoft Serial Mouse */ &mouse_serial_logitech, /* 5 Logitech 3-button Serial Mouse */ &mouse_serial_mswheel, /* 6 Microsoft Serial Wheel Mouse */ - &mouse_ps2_2_button, /* 7 PS/2 Mouse 2-button */ - &mouse_intellimouse, /* 8 PS/2 Intellimouse 3-button */ + &mouse_ps2_2button, /* 7 PS/2 Mouse 2-button */ + &mouse_ps2_intellimouse, /* 8 PS/2 Intellimouse 3-button */ &mouse_amstrad, /* 9 Amstrad PC System Mouse */ &mouse_olim24, /* 10 Olivetti M24 System Mouse */ #if 0 - &mouse_genius, /* 11 Genius Bus Mouse */ + &mouse_bus_genius, /* 11 Genius Bus Mouse */ #endif NULL }; diff --git a/src/mouse.h b/src/mouse.h index b79f3492d..86eb01e3c 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -8,7 +8,7 @@ * * Definitions for the MOUSE driver. * - * Version: @(#)mouse.h 1.0.3 2017/06/21 + * Version: @(#)mouse.h 1.0.4 2017/07/27 * * Authors: Sarah Walker, * Miran Grca, @@ -20,20 +20,22 @@ # define EMU_MOUSE_H -#define MOUSE_TYPE_NONE 0 -#if 0 -#define MOUSE_TYPE_GENIUS 11 /* Genius Bus Mouse */ -#endif -#define MOUSE_TYPE_BUS 1 /* Logitech/ATI Bus Mouse */ -#define MOUSE_TYPE_INPORT 2 /* Microsoft InPort Mouse */ -#define MOUSE_TYPE_MSYSTEMS 3 /* Mouse Systems mouse */ -#define MOUSE_TYPE_SERIAL 4 /* Serial Mouse */ -#define MOUSE_TYPE_LOGITECH 5 /* Logitech Serial Mouse */ -#define MOUSE_TYPE_MSWHEEL 6 /* Serial Wheel Mouse */ -#define MOUSE_TYPE_PS2 7 /* IBM PS/2 series Bus Mouse */ -#define MOUSE_TYPE_PS2_MS 8 /* Microsoft Intellimouse PS/2 */ -#define MOUSE_TYPE_AMSTRAD 9 /* Amstrad PC system mouse */ +#define SERMOUSE_PORT 1 /* attach to Serial1 */ + +#define MOUSE_TYPE_NONE 0 +#define MOUSE_TYPE_LOGIBUS 1 /* Logitech/ATI Bus Mouse */ +#define MOUSE_TYPE_INPORT 2 /* Microsoft InPort Mouse */ +#define MOUSE_TYPE_MSYSTEMS 3 /* Mouse Systems mouse */ +#define MOUSE_TYPE_MICROSOFT 4 /* Microsoft Serial Mouse */ +#define MOUSE_TYPE_LOGITECH 5 /* Logitech Serial Mouse */ +#define MOUSE_TYPE_MSWHEEL 6 /* Serial Wheel Mouse */ +#define MOUSE_TYPE_PS2 7 /* IBM PS/2 series Bus Mouse */ +#define MOUSE_TYPE_PS2_MS 8 /* Microsoft Intellimouse PS/2 */ +#define MOUSE_TYPE_AMSTRAD 9 /* Amstrad PC system mouse */ #define MOUSE_TYPE_OLIM24 10 /* Olivetti M24 system mouse */ +#if 0 +# define MOUSE_TYPE_GENIUS 11 /* Genius Bus Mouse */ +#endif #define MOUSE_TYPE_MASK 0x0f #define MOUSE_TYPE_3BUTTON (1<<7) /* device has 3+ buttons */ @@ -51,9 +53,21 @@ typedef struct { extern int mouse_type; +extern mouse_t mouse_bus_logitech; +extern mouse_t mouse_bus_msinport; +extern mouse_t mouse_serial_msystems; +extern mouse_t mouse_serial_microsoft; +extern mouse_t mouse_serial_logitech; +extern mouse_t mouse_serial_mswheel; +extern mouse_t mouse_ps2_2button; +extern mouse_t mouse_ps2_intellimouse; + + +extern void *mouse_ps2_init(void); extern void mouse_emu_init(void); extern void mouse_emu_close(void); + extern void mouse_poll(int x, int y, int z, int b); extern char *mouse_get_name(int mouse); extern char *mouse_get_internal_name(int mouse); diff --git a/src/mouse_bus.c b/src/mouse_bus.c index ea315dd0d..526c3dc02 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -32,7 +32,7 @@ * Based on an early driver for MINIX 1.5. * Based on the 86Box PS/2 mouse driver as a framework. * - * Version: @(#)mouse_bus.c 1.0.6 2017/07/24 + * Version: @(#)mouse_bus.c 1.0.7 2017/07/27 * * Author: Fred N. van Kempen, * TheCollector1995, @@ -45,13 +45,12 @@ #include "pic.h" #include "timer.h" #include "mouse.h" -#include "mouse_bus.h" -#include "plat_mouse.h" + #define BUS_MOUSE_IRQ 5 #define IRQ_MASK ((1<<5) >> BUS_MOUSE_IRQ) -// MS Inport Bus Mouse Adapter +/* MS Inport Bus Mouse Adapter. */ #define INP_PORT_CONTROL 0x023C #define INP_PORT_DATA 0x023D #define INP_PORT_SIGNATURE 0x023E @@ -67,7 +66,7 @@ #define INP_HOLD_COUNTER (1 << 5) #define INP_ENABLE_IRQ (1 << 0) -// MS/Logictech Standard Bus Mouse Adapter +/* MS/Logictech Standard Bus Mouse Adapter. */ #define BUSM_PORT_DATA 0x023C #define BUSM_PORT_SIGNATURE 0x023D #define BUSM_PORT_CONTROL 0x023E @@ -462,17 +461,17 @@ static void *inport_init(void) return(inport); } -mouse_t mouse_bus = +mouse_t mouse_bus_logitech = { - "Bus Mouse", + "Logitech Bus Mouse", "msbus", - MOUSE_TYPE_BUS, + MOUSE_TYPE_LOGIBUS, busmouse_init, busmouse_close, busmouse_poll }; -mouse_t mouse_inport = +mouse_t mouse_bus_msinport = { "InPort Mouse", "inport", diff --git a/src/mouse_bus.h b/src/mouse_bus.h deleted file mode 100644 index 3f931ca86..000000000 --- a/src/mouse_bus.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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. - * - * Implementation of Bus Mouse devices. - * - * These mice devices were made by both Microsoft (InPort) and - * Logitech. Sadly, they did not use the same I/O protocol, but - * they were close enough to fit into a single implementation. - * - * Definitions for the Bus Mouse driver. - * - * Version: @(#)mouse_bus.h 1.0.3 2017/04/22 - * - * Author: Fred N. van Kempen, - * Copyright 1989-2017 Fred N. van Kempen. - */ -#ifndef MOUSE_BUS_H -# define MOUSE_BUS_H - - -extern mouse_t mouse_bus; -extern mouse_t mouse_inport; - - -#endif /*MOUSE_BUS_H*/ diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c index d5627eda8..d8cad2e1b 100644 --- a/src/mouse_ps2.c +++ b/src/mouse_ps2.c @@ -2,7 +2,6 @@ #include "ibm.h" #include "keyboard_at.h" #include "mouse.h" -#include "mouse_ps2.h" #include "plat_mouse.h" @@ -238,16 +237,18 @@ void mouse_ps2_close(void *p) free(mouse); } -mouse_t mouse_ps2_2_button = + +mouse_t mouse_ps2_2button = { - "2-button mouse (PS/2)", + "Standard 2-button mouse (PS/2)", "ps2", MOUSE_TYPE_PS2, mouse_ps2_init, mouse_ps2_close, mouse_ps2_poll }; -mouse_t mouse_intellimouse = + +mouse_t mouse_ps2_intellimouse = { "Microsoft Intellimouse (PS/2)", "intellimouse", diff --git a/src/mouse_ps2.h b/src/mouse_ps2.h deleted file mode 100644 index b25cae5f2..000000000 --- a/src/mouse_ps2.h +++ /dev/null @@ -1,4 +0,0 @@ -extern mouse_t mouse_ps2_2_button; -extern mouse_t mouse_intellimouse; - -extern void *mouse_ps2_init(); diff --git a/src/mouse_serial.c b/src/mouse_serial.c index bbad6b0d8..d2446c3a3 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -10,7 +10,7 @@ * * Based on the 86Box Serial Mouse driver as a framework. * - * Version: @(#)mouse_serial.c 1.0.6 2017/06/19 + * Version: @(#)mouse_serial.c 1.0.7 2017/07/27 * * Author: Fred N. van Kempen, */ @@ -19,13 +19,6 @@ #include "timer.h" #include "serial.h" #include "mouse.h" -#include "mouse_serial.h" - - -#ifdef WALTJE -#define SERMOUSE_TYPE_MSYSTEMS 1 /* Mouse Systems */ -#define SERMOUSE_TYPE_MICROSOFT 2 /* Microsoft */ -#define SERMOUSE_TYPE_LOGITECH 3 /* Logitech */ typedef struct mouse_serial_t { @@ -40,7 +33,11 @@ typedef struct mouse_serial_t { /* Callback from serial driver: RTS was toggled. */ static void +#ifdef WALTJE sermouse_callback(void *priv) +#else +sermouse_callback(struct SERIAL *serial, void *priv) +#endif { mouse_serial_t *ms = (mouse_serial_t *)priv; @@ -58,20 +55,49 @@ sermouse_timer(void *priv) ms->delay = 0; - switch(ms->type) { - case SERMOUSE_TYPE_MICROSOFT: - /* This identifies a two-button Microsoft Serial mouse. */ - serial_write_fifo(ms->serial, 'M', 1); + if (ms->pos != -1) return; + + ms->pos = 0; + switch(ms->type & MOUSE_TYPE_MASK) { + case MOUSE_TYPE_MSYSTEMS: + /* Identifies Mouse Systems serial mouse. */ +#ifdef WALTJE + serial_write_fifo(ms->serial, 'H', 1); +#else + serial_write_fifo(ms->serial, 'H'); +#endif break; - case SERMOUSE_TYPE_LOGITECH: - /* This identifies a two-button Logitech Serial mouse. */ + case MOUSE_TYPE_MICROSOFT: + default: + /* Identifies a two-button Microsoft Serial mouse. */ +#ifdef WALTJE + serial_write_fifo(ms->serial, 'M', 1); +#else + serial_write_fifo(ms->serial, 'M'); +#endif + break; + + case MOUSE_TYPE_LOGITECH: + /* Identifies a two-button Logitech Serial mouse. */ +#ifdef WALTJE serial_write_fifo(ms->serial, 'M', 1); serial_write_fifo(ms->serial, '3', 1); +#else + serial_write_fifo(ms->serial, 'M'); + serial_write_fifo(ms->serial, '3'); +#endif break; - default: - /* No action needed. */ + case MOUSE_TYPE_MSWHEEL: + /* Identifies multi-button Microsoft Wheel Mouse. */ +#ifdef WALTJE + serial_write_fifo(ms->serial, 'M', 1); + serial_write_fifo(ms->serial, 'Z', 1); +#else + serial_write_fifo(ms->serial, 'M'); + serial_write_fifo(ms->serial, 'Z'); +#endif break; } } @@ -88,7 +114,7 @@ sermouse_poll(int x, int y, int z, int b, void *priv) ms->oldb = b; - if (ms->type == SERMOUSE_TYPE_MSYSTEMS) y = -y; + if (ms->type == MOUSE_TYPE_MSYSTEMS) y = -y; if (x>127) x = 127; if (y>127) y = 127; @@ -96,8 +122,8 @@ sermouse_poll(int x, int y, int z, int b, void *priv) if (y<-128) y = -128; len = 0; - switch(ms->type) { - case SERMOUSE_TYPE_MSYSTEMS: + switch(ms->type & MOUSE_TYPE_MASK) { + case MOUSE_TYPE_MSYSTEMS: buff[0] = 0x80; buff[0] |= (b&0x01) ? 0x00 : 0x04; /* left button */ buff[0] |= (b&0x02) ? 0x00 : 0x01; /* middle button */ @@ -109,10 +135,10 @@ sermouse_poll(int x, int y, int z, int b, void *priv) len = 5; break; - case SERMOUSE_TYPE_MICROSOFT: + case MOUSE_TYPE_MICROSOFT: buff[0] = 0x40; - buff[0] |= (((y>>6)&03)<<2); - buff[0] |= ((x>>6)&03); + buff[0] |= (((y>>6)&0x03)<<2); + buff[0] |= ((x>>6)&0x03); if (b&0x01) buff[0] |= 0x20; if (b&0x02) buff[0] |= 0x10; buff[1] = x & 0x3F; @@ -120,21 +146,34 @@ sermouse_poll(int x, int y, int z, int b, void *priv) len = 3; break; - case SERMOUSE_TYPE_LOGITECH: + case MOUSE_TYPE_LOGITECH: buff[0] = 0x40; - buff[0] |= (((y>>6)&03)<<2); - buff[0] |= ((x>>6)&03); + buff[0] |= (((y>>6)&0x03)<<2); + buff[0] |= ((x>>6)&0x03); if (b&0x01) buff[0] |= 0x20; if (b&0x02) buff[0] |= 0x10; buff[1] = x & 0x3F; buff[2] = y & 0x3F; + len = 3; if (b&0x04) { buff[3] = 0x20; - len = 4; - } else { - len = 3; + len++; } break; + + case MOUSE_TYPE_MSWHEEL: + buff[0] = 0x40; + buff[0] |= (((y>>6)&0x03)<<2); + buff[0] |= ((x>>6)&0x03); + if (b&0x01) buff[0] |= 0x20; + if (b&0x02) buff[0] |= 0x10; + buff[1] = x & 0x3F; + buff[2] = y & 0x3F; + buff[3] = z & 0x0F; + if (b&0x04) + buff[3] |= 0x10; + len = 4; + } #if 0 @@ -145,7 +184,11 @@ sermouse_poll(int x, int y, int z, int b, void *priv) /* Send the packet to the bottom-half of the attached port. */ for (b=0; bserial, buff[b], 1); +#else + serial_write_fifo(ms->serial, buff[b]); +#endif return(0); } @@ -157,7 +200,11 @@ sermouse_close(void *priv) mouse_serial_t *ms = (mouse_serial_t *)priv; /* Detach serial port from the mouse. */ +#ifdef WALTJE serial_attach(ms->port, NULL, NULL); +#else + serial1.rcr_callback = NULL; +#endif free(ms); } @@ -172,7 +219,12 @@ sermouse_init(int type) ms->type = type; /* Attach a serial port to the mouse. */ +#ifdef WALTJE ms->serial = serial_attach(ms->port, sermouse_callback, ms); +#else + ms->serial = &serial1; + ms->serial->rcr_callback = sermouse_callback; +#endif timer_add(sermouse_timer, &ms->delay, &ms->delay, ms); @@ -180,31 +232,38 @@ sermouse_init(int type) } +static void * +sermouse_init_msystems(void) +{ + return(sermouse_init(MOUSE_TYPE_MSYSTEMS)); +} + + static void * sermouse_init_microsoft(void) { - return(sermouse_init(SERMOUSE_TYPE_MICROSOFT)); + return(sermouse_init(MOUSE_TYPE_MICROSOFT)); } static void * sermouse_init_logitech(void) { - return(sermouse_init(SERMOUSE_TYPE_LOGITECH)); + return(sermouse_init(MOUSE_TYPE_LOGITECH)); } static void * -sermouse_init_msystems(void) +sermouse_init_mswheel(void) { - return(sermouse_init(SERMOUSE_TYPE_MSYSTEMS)); + return(sermouse_init(MOUSE_TYPE_MSWHEEL)); } -mouse_t mouse_msystems = { +mouse_t mouse_serial_msystems = { "Mouse Systems Mouse (serial)", "mssystems", - MOUSE_TYPE_MSYSTEMS, + MOUSE_TYPE_MSYSTEMS | MOUSE_TYPE_3BUTTON, sermouse_init_msystems, sermouse_close, sermouse_poll @@ -214,7 +273,7 @@ mouse_t mouse_msystems = { mouse_t mouse_serial_microsoft = { "Microsoft 2-button mouse (serial)", "msserial", - MOUSE_TYPE_SERIAL, + MOUSE_TYPE_MICROSOFT, sermouse_init_microsoft, sermouse_close, sermouse_poll @@ -224,232 +283,18 @@ mouse_t mouse_serial_microsoft = { mouse_t mouse_serial_logitech = { "Logitech 3-button mouse (serial)", "lserial", - MOUSE_TYPE_SERIAL | MOUSE_TYPE_3BUTTON, + MOUSE_TYPE_LOGITECH | MOUSE_TYPE_3BUTTON, sermouse_init_logitech, sermouse_close, sermouse_poll }; -#else - - -typedef struct mouse_serial_t -{ - int mousepos, mousedelay; - int oldb; - int type; - SERIAL *serial; -} mouse_serial_t; - -uint8_t mouse_serial_poll(int x, int y, int z, int b, void *p) -{ - mouse_serial_t *mouse = (mouse_serial_t *)p; - SERIAL *serial = mouse->serial; - uint8_t mousedat[4]; - - if (!(serial->ier & 1)) - return 0xff; - if (!x && !y && b == mouse->oldb) - return 0xff; - - mouse->oldb = b; - if (x>127) x=127; - if (y>127) y=127; - if (x<-128) x=-128; - if (y<-128) y=-128; - - /*Use Microsoft format*/ - mousedat[0]=0x40; - mousedat[0]|=(((y>>6)&3)<<2); - mousedat[0]|=((x>>6)&3); - if (b&1) mousedat[0]|=0x20; - if (b&2) mousedat[0]|=0x10; - mousedat[1]=x&0x3F; - mousedat[2]=y&0x3F; - - if (!(serial->mctrl & 0x10)) - { - serial_write_fifo(mouse->serial, mousedat[0]); - serial_write_fifo(mouse->serial, mousedat[1]); - serial_write_fifo(mouse->serial, mousedat[2]); - if (mouse->type == 2) - { - if (b&0x04) - { - serial_write_fifo(mouse->serial, 0x20); - } - } - else if (mouse->type == 3) - { - mousedat[3] = z & 0xf; - if (b&4) mousedat[3] |= 0x10; - serial_write_fifo(mouse->serial, mousedat[3]); - } - } - - return 0; -} - -uint8_t mouse_serial_msystems_poll(int x, int y, int z, int b, void *p) -{ - mouse_serial_t *mouse = (mouse_serial_t *)p; - SERIAL *serial = mouse->serial; - uint8_t mousedat[5]; - - if (!x && !y && b == mouse->oldb) - return 0xff; - - y = -y; - - mouse->oldb = b; - if (x>127) x=127; - if (y>127) y=127; - if (x<-128) x=-128; - if (y<-128) y=-128; - - /*Use Mouse Systems format*/ - mousedat[0] = 0x80; - mousedat[0] |= (b&0x01) ? 0x00 : 0x04; /* left button */ - mousedat[0] |= (b&0x02) ? 0x00 : 0x01; /* middle button */ - mousedat[0] |= (b&0x04) ? 0x00 : 0x02; /* right button */ - mousedat[1] = x; - mousedat[2] = y; - mousedat[3] = x; /* same as byte 1 */ - mousedat[4] = y; /* same as byte 2 */ - - if (!(serial->mctrl & 0x10)) - { - serial_write_fifo(mouse->serial, mousedat[0]); - serial_write_fifo(mouse->serial, mousedat[1]); - serial_write_fifo(mouse->serial, mousedat[2]); - serial_write_fifo(mouse->serial, mousedat[3]); - serial_write_fifo(mouse->serial, mousedat[4]); - } - - return 0; -} - -void mouse_serial_rcr(struct SERIAL *serial, void *p) -{ - mouse_serial_t *mouse = (mouse_serial_t *)p; - - mouse->mousepos = -1; - mouse->mousedelay = 5000 * (1 << TIMER_SHIFT); -} - -void mousecallback(void *p) -{ - mouse_serial_t *mouse = (mouse_serial_t *)p; - - mouse->mousedelay = 0; - if (mouse->mousepos == -1) - { - mouse->mousepos = 0; - switch(mouse->type) - { - case 0: - serial_write_fifo(mouse->serial, 'H'); - break; - case 1: - default: - serial_write_fifo(mouse->serial, 'M'); - break; - case 2: - serial_write_fifo(mouse->serial, 'M'); - serial_write_fifo(mouse->serial, '3'); - break; - case 3: - serial_write_fifo(mouse->serial, 'M'); - serial_write_fifo(mouse->serial, 'Z'); - break; - } - } -} - -void *mouse_serial_common_init(int type) -{ - mouse_serial_t *mouse = (mouse_serial_t *)malloc(sizeof(mouse_serial_t)); - memset(mouse, 0, sizeof(mouse_serial_t)); - - mouse->serial = &serial1; - serial1.rcr_callback = mouse_serial_rcr; - serial1.rcr_callback_p = mouse; - timer_add(mousecallback, &mouse->mousedelay, &mouse->mousedelay, mouse); - - mouse->type = type; - - return mouse; -} - -void *mouse_serial_msystems_init() -{ - return mouse_serial_common_init(0); -} - -void *mouse_serial_init() -{ - return mouse_serial_common_init(1); -} - -void *mouse_serial_logitech_init() -{ - return mouse_serial_common_init(2); -} - -void *mouse_serial_mswheel_init() -{ - return mouse_serial_common_init(3); -} - -void mouse_serial_close(void *p) -{ - mouse_serial_t *mouse = (mouse_serial_t *)p; - - free(mouse); - - serial1.rcr_callback = NULL; -} - -mouse_t mouse_msystems = -{ - "Mouse Systems Mouse (serial)", - "mssystems", - MOUSE_TYPE_MSYSTEMS | MOUSE_TYPE_3BUTTON, - mouse_serial_msystems_init, - mouse_serial_close, - mouse_serial_msystems_poll +mouse_t mouse_serial_mswheel = { + "Microsoft wheel mouse (serial)", + "mswheel", + MOUSE_TYPE_MSWHEEL | MOUSE_TYPE_3BUTTON, + sermouse_init_mswheel, + sermouse_close, + sermouse_poll }; - -mouse_t mouse_serial_microsoft = -{ - "Microsoft 2-button mouse (serial)", - "msserial", - MOUSE_TYPE_SERIAL, - mouse_serial_init, - mouse_serial_close, - mouse_serial_poll -}; - -mouse_t mouse_serial_logitech = -{ - "Logitech 3-button mouse (serial)", - "lserial", - MOUSE_TYPE_LOGITECH | MOUSE_TYPE_3BUTTON, - mouse_serial_logitech_init, - mouse_serial_close, - mouse_serial_poll -}; - -mouse_t mouse_serial_mswheel = -{ - "Microsoft wheel mouse (serial)", - "mssystems", - MOUSE_TYPE_MSWHEEL | MOUSE_TYPE_3BUTTON, - mouse_serial_mswheel_init, - mouse_serial_close, - mouse_serial_poll -}; - - -#endif \ No newline at end of file diff --git a/src/mouse_serial.h b/src/mouse_serial.h deleted file mode 100644 index f6c5a45d1..000000000 --- a/src/mouse_serial.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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. - * - * Implementation of Serial Mouse devices. - * - * Definitions for the Serial Mouse driver. - * - * Version: @(#)mouse_serial.h 1.0.3 2017/06/19 - * - * Author: Fred N. van Kempen, - */ -#ifndef MOUSE_SERIAL_H -# define MOUSE_SERIAL_H - - -#define SERMOUSE_PORT 1 /* attach to Serial1 */ - - -extern mouse_t mouse_msystems; -extern mouse_t mouse_serial_microsoft; -extern mouse_t mouse_serial_logitech; -extern mouse_t mouse_serial_mswheel; - - -#endif /*MOUSE_SERIAL_H*/ diff --git a/src/scsi.h b/src/scsi.h index d0e4bfb91..68200572b 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -5,7 +5,11 @@ #define SCSI_H +#ifdef WALTJE +#define SCSI_TIME (50 * (1 << TIMER_SHIFT)) +#else #define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#endif /* SCSI commands. */ diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index d3a27084c..3259c5e58 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -39,6 +39,9 @@ #include "scsi_aha154x.h" +#define SCSI_DELAY_TM 1 /* was 50 */ + + #define AHA AHA154xCF /* set desired card type */ #define AHA154xB 1 /* AHA-154x Rev.B */ #define AHA154xC 2 /* AHA-154x Rev.C */ @@ -419,8 +422,9 @@ again: aha_eep[0] |= (0x10 | 0x20 | 0x40); aha_eep[1] = irq-9; /* IRQ15 */ aha_eep[1] |= (dma<<4); /* DMA6 */ - aha_eep[2] = (EE2_DYNSCAN | /* BIOS Space Reserved */ - EE2_EXT1G | EE2_RMVOK); /* Immediate return on seek */ + aha_eep[2] = (EE2_HABIOS | /* BIOS enabled */ + EE2_DYNSCAN | /* scan bus */ + EE2_EXT1G | EE2_RMVOK);/* Immediate return on seek */ aha_eep[3] = SPEED_50; /* speed 5.0 MB/s */ aha_eep[6] = (EE6_TERM | /* host term enable */ EE6_RSTBUS); /* reset SCSI bus on boot */ @@ -1371,7 +1375,7 @@ aha_write(uint16_t port, uint8_t val, void *priv) /* If there are no mailboxes configured, don't even try to do anything. */ if (dev->MailboxCount) { if (!AHA_Callback) { - AHA_Callback = 50 * SCSI_TIME; + AHA_Callback = SCSI_DELAY_TM * SCSI_TIME; } } return; @@ -2106,7 +2110,7 @@ aha_cmd_cb(void *priv) if (dev->MailboxCount) { aha_do_mail(dev); } else { - AHA_Callback += 50 * SCSI_TIME; + AHA_Callback += SCSI_DELAY_TM * SCSI_TIME; return; } } else if (AHA_InOperation == 1) { @@ -2128,7 +2132,7 @@ aha_cmd_cb(void *priv) fatal("Invalid BusLogic callback phase: %i\n", AHA_InOperation); } - AHA_Callback += 50 * SCSI_TIME; + AHA_Callback += SCSI_DELAY_TM * SCSI_TIME; } uint8_t aha_mca_read(int port, void *p) diff --git a/src/serial.c b/src/serial.c index ad200a9ba..2789d85f6 100644 --- a/src/serial.c +++ b/src/serial.c @@ -186,8 +186,11 @@ update_ints(SERIAL *sp) sp->iir = IID_IDMDM; } + /* If IRQ line not enabled, done. */ + if (!(sp->mctrl & MCR_OUT2) && !PCJR) return; + /* Raise or clear the level-based IRQ. */ - if (stat && ((sp->mctrl & MCR_OUT2) || PCJR)) + if (stat) picintlevel(1 << sp->irq); else picintc(1 << sp->irq); @@ -291,26 +294,30 @@ serial_write(uint16_t addr, uint8_t val, void *priv) break; case 3: /* LCR */ - if ((sp->lcr & LCR_DLAB) && !(val & LCR_DLAB)) { - /* We dropped DLAB, so handle baudrate. */ - baud = ((sp->dlab2<<8) | sp->dlab1); - if (baud > 0) { - speed = 115200UL/baud; - serial_log(2, "Serial%d: divisor %u, baudrate %ld\n", - sp->port, baud, speed); - if ((sp->bh != NULL) && (speed > 0)) - bhtty_speed((BHTTY *)sp->bh, speed); + if (! (val & LCR_DLAB)) { + /* DLAB clear. Was it set? */ + if (sp->lcr & LCR_DLAB) { + /* We dropped DLAB, so handle baudrate. */ + baud = ((sp->dlab2<<8) | sp->dlab1); + if (baud > 0) { + speed = 115200UL/baud; + serial_log(2, "Serial%d: divisor %u, baudrate %ld\n", + sp->port, baud, speed); + if ((sp->bh != NULL) && (speed > 0)) + bhtty_speed((BHTTY *)sp->bh, speed); + } else { + serial_log(1, "Serial%d: divisor %u invalid!\n", + sp->port, baud); + } } else { - serial_log(1, "Serial%d: divisor %u invalid!\n", - sp->port, baud); + wl = (val & LCR_WLS) + 5; /* databits */ + sb = (val & LCR_SBS) ? 2 : 1; /* stopbits */ + pa = (val & (LCR_PE|LCR_EP|LCR_PS)) >> 3; + serial_log(2, "Serial%d: WL=%d SB=%d PA=%d\n", sp->port, wl, sb, pa); + if (sp->bh != NULL) + bhtty_params((BHTTY *)sp->bh, wl, pa, sb); } } - wl = (val & LCR_WLS) + 5; /* databits */ - sb = (val & LCR_SBS) ? 2 : 1; /* stopbits */ - pa = (val & (LCR_PE|LCR_EP|LCR_PS)) >> 3; - serial_log(2, "Serial%d: WL=%d SB=%d PA=%d\n", sp->port, wl, sb, pa); - if (sp->bh != NULL) - bhtty_params((BHTTY *)sp->bh, wl, pa, sb); sp->lcr = val; break; @@ -338,12 +345,14 @@ serial_write(uint16_t addr, uint8_t val, void *priv) &sp->receive_delay, &sp->receive_delay, sp); +#if 0 /* Fake CTS, DSR and DCD (for now.) */ sp->msr = (MSR_CTS | MSR_DCTS | MSR_DSR | MSR_DDSR | MSR_DCD | MSR_DDCD); sp->int_status |= SERINT_MSR; update_ints(sp); +#endif } } sp->mctrl = val; @@ -424,7 +433,9 @@ serial_read(uint16_t addr, void *priv) } else { sp->lsr &= ~LSR_DR; sp->int_status &= ~SERINT_RECEIVE; +#if 0 update_ints(sp); +#endif ret = read_fifo(sp); if ((sp->bh == NULL) && (sp->fifo_read != sp->fifo_write)) From f8a92d0165f97f72aeb0eb6ea50b0134df41cd73 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 4 Aug 2017 15:18:38 +0200 Subject: [PATCH 59/82] Logitech bus mouse now identifies correctly in Settings; Serial mouse initialization now sets up rcr_callback_p, fixes emulator segmentation fault on CuteMouse load. --- src/WIN/86Box.rc | 2 +- src/mouse_serial.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/WIN/86Box.rc b/src/WIN/86Box.rc index 05381bd48..776fd8350 100644 --- a/src/WIN/86Box.rc +++ b/src/WIN/86Box.rc @@ -843,7 +843,7 @@ BEGIN IDS_2170 "Check BPB" IDS_3072 "None" - IDS_3073 "[Bus] Bus mouse" + IDS_3073 "[Bus] Logitech Bus mouse" IDS_3074 "[Bus] InPort mouse" IDS_3075 "[Serial] Mouse Systems mouse" IDS_3076 "[Serial] Microsoft 2-button mouse" diff --git a/src/mouse_serial.c b/src/mouse_serial.c index d2446c3a3..422de2045 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -224,6 +224,7 @@ sermouse_init(int type) #else ms->serial = &serial1; ms->serial->rcr_callback = sermouse_callback; + ms->serial->rcr_callback_p = ms; #endif timer_add(sermouse_timer, &ms->delay, &ms->delay, ms); From 064c9eb684f2ba5cf9cc4910e367cbf5c9dd4fc0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 5 Aug 2017 14:34:58 +0200 Subject: [PATCH 60/82] Applied the mainline PCem commit that fixes the rendering of Amulets & Armor. --- src/VIDEO/vid_svga.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/VIDEO/vid_svga.c b/src/VIDEO/vid_svga.c index 01542b93b..d59b043be 100644 --- a/src/VIDEO/vid_svga.c +++ b/src/VIDEO/vid_svga.c @@ -251,6 +251,10 @@ void svga_out(uint16_t addr, uint8_t val, void *p) svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r, svga->vgapal[svga->dac_write].g, svga->vgapal[svga->dac_write].b); else { + svga->vgapal[svga->dac_write].r &= 0x3f; + svga->vgapal[svga->dac_write].g &= 0x3f; + svga->vgapal[svga->dac_write].b &= 0x3f; + if ((romset == ROM_IBMPS1_2011) || (romset == ROM_IBMPS1_2121) || (romset == ROM_IBMPS2_M30_286)) { svga->pallook[svga->dac_write] = makecol32((svga->vgapal[svga->dac_write].r & 0x3f) * 4, (svga->vgapal[svga->dac_write].g & 0x3f) * 4, (svga->vgapal[svga->dac_write].b & 0x3f) * 4); From 523c6b65d18a85acc4044b5eb796f589d131477b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 6 Aug 2017 00:33:47 +0200 Subject: [PATCH 61/82] serial_setup() in serial_old.c now returns without doing anything if the specified serial port is disabled in Settings, fixes ports being enabled where they shouldn't be on machines with Super I/O chips; LPT code now takes the lpt_enabled variable into account at all levels. --- src/lpt.c | 40 +++++++++++++++++++++++++++++----------- src/serial_old.c | 8 ++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/lpt.c b/src/lpt.c index 73cd3ce6d..eb25900af 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -61,32 +61,50 @@ uint16_t lpt_addr[2] = { 0x378, 0x278 }; void lpt_init() { - io_sethandler(0x0378, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); - io_sethandler(0x0278, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); - lpt_addr[0] = 0x378; - lpt_addr[1] = 0x278; + if (lpt_enabled) + { + io_sethandler(0x0378, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); + io_sethandler(0x0278, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + lpt_addr[0] = 0x378; + lpt_addr[1] = 0x278; + } } void lpt1_init(uint16_t port) { - io_sethandler(port, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); - lpt_addr[0] = port; + if (lpt_enabled) + { + io_sethandler(port, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); + lpt_addr[0] = port; + } } void lpt1_remove() { - io_removehandler(lpt_addr[0], 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); + if (lpt_enabled) + { + io_removehandler(lpt_addr[0], 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); + } } void lpt2_init(uint16_t port) { - io_sethandler(port, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); - lpt_addr[1] = port; + if (lpt_enabled) + { + io_sethandler(port, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + lpt_addr[1] = port; + } } void lpt2_remove() { - io_removehandler(lpt_addr[1], 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + if (lpt_enabled) + { + io_removehandler(lpt_addr[1], 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + } } void lpt2_remove_ams() { - io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + if (lpt_enabled) + { + io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + } } diff --git a/src/serial_old.c b/src/serial_old.c index 7dbb3e928..a195c310e 100644 --- a/src/serial_old.c +++ b/src/serial_old.c @@ -286,6 +286,10 @@ void serial_setup(int port, uint16_t addr, int irq) switch(port) { case 1: + if (!serial_enabled[0]) + { + return; + } if (base_address[0] != 0x0000) { serial_remove(port); @@ -298,6 +302,10 @@ void serial_setup(int port, uint16_t addr, int irq) serial1.irq = irq; break; case 2: + if (!serial_enabled[1]) + { + return; + } if (base_address[1] != 0x0000) { serial_remove(port); From d69539ef245517b14c3453c1bd3e1e6113d3c545 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Aug 2017 02:53:24 +0200 Subject: [PATCH 62/82] Fixed a source of crashes in slirp.c. --- src/NETWORK/slirp/slirp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NETWORK/slirp/slirp.c b/src/NETWORK/slirp/slirp.c index 3068dc72c..785d971f5 100644 --- a/src/NETWORK/slirp/slirp.c +++ b/src/NETWORK/slirp/slirp.c @@ -253,9 +253,10 @@ int slirp_select_fill(int *pnfds, /* * See if we need a tcp_fasttimo */ + if(so->so_tcpcb!=0x0){ if(&so->so_tcpcb->t_flags!=0x0){ //This is to prevent a common lockup. if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) - time_fasttimo = curtime; }/* Flag when we want a fasttimo */ + time_fasttimo = curtime; } } /* Flag when we want a fasttimo */ /* From 13f7358ae537557e5ccc524f2cf21b507e4f87cb Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Aug 2017 22:57:11 +0200 Subject: [PATCH 63/82] Added FluidSynth MIDI device and the two new device configuration types, per PCem patches from bit. --- src/Makefile.mingw | 3 +- src/SOUND/midi.c | 6 +- src/WIN/win_deviceconfig.c | 306 ++++++++++++++++++++++++++++++++++--- src/WIN/win_language.c | 9 ++ src/WIN/win_language.h | 1 + src/device.h | 23 ++- 6 files changed, 320 insertions(+), 28 deletions(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index ef0636e31..8c34794bb 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -203,6 +203,7 @@ SNDOBJ = sound.o \ wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ wave8580_PST.o wave.o \ midi.o \ + midi_fluidsynth.o \ midi_mt32.o \ Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ LA32FloatWaveGenerator.o LA32WaveGenerator.o \ @@ -262,7 +263,7 @@ LIBS = -mwindows \ -lopenal.dll \ -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ -lcomctl32 -lkernel32 -lwsock32 -lwinmm -liphlpapi -lpsapi \ - -static -lstdc++ -lgcc + -static -lstdc++ -lgcc -lfluidsynth -lfluidsynth.dll # Build rules. diff --git a/src/SOUND/midi.c b/src/SOUND/midi.c index 6f3de8fba..9a80e30f2 100644 --- a/src/SOUND/midi.c +++ b/src/SOUND/midi.c @@ -8,8 +8,9 @@ #include "../WIN/plat_midi.h" #include "../WIN/plat_ticks.h" -#include "midi_system.h" +#include "midi_fluidsynth.h" #include "midi_mt32.h" +#include "midi_system.h" int midi_device_current = 0; static int midi_device_last = 0; @@ -24,9 +25,10 @@ typedef struct static MIDI_DEVICE devices[] = { {"None", "none", NULL}, - {SYSTEM_MIDI_NAME, SYSTEM_MIDI_INTERNAL_NAME, &system_midi_device}, + {"FluidSynth", "fluidsynth", &fluidsynth_device}, {"Roland MT-32 Emulation", "mt32", &mt32_device}, {"Roland CM-32L Emulation", "cm32l", &cm32l_device}, + {SYSTEM_MIDI_NAME, SYSTEM_MIDI_INTERNAL_NAME, &system_midi_device}, {"", "", NULL} }; diff --git a/src/WIN/win_deviceconfig.c b/src/WIN/win_deviceconfig.c index 3cce23331..920595db0 100644 --- a/src/WIN/win_deviceconfig.c +++ b/src/WIN/win_deviceconfig.c @@ -35,10 +35,11 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam int val_int; int ret; int id; - device_config_t *config; int c; - int num; + int num; int changed; + int cid; + device_config_t *config; char s[80]; switch (message) @@ -94,6 +95,24 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam id += 2; break; + case CONFIG_SPINNER: + val_int = config_get_int(config_device->name, config->name, config->default_int); + + sprintf(s, "%i", val_int); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + + id += 2; + break; + + case CONFIG_FILE: + { + char* str = config_get_string(config_device->name, config->name, 0); + if (str) + SendMessage(h, WM_SETTEXT, 0, (LPARAM)str); + id += 3; + } + break; + case CONFIG_HEX16: val_int = config_get_hex16(config_device->name, config->name, config->default_int); @@ -132,13 +151,14 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam return TRUE; case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - { + { + cid = LOWORD(wParam); + if (cid == IDOK) + { id = IDC_CONFIG_BASE; config = config_device->config; changed = 0; + char s[512]; while (config->type != -1) { @@ -181,6 +201,33 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam id += 2; break; + case CONFIG_FILE: + { + char* str = config_get_string(config_device->name, config->name, (char*)""); + SendMessage(h, WM_GETTEXT, 511, (LPARAM)s); + if (strcmp(str, s)) + changed = 1; + + id += 3; + } + break; + + case CONFIG_SPINNER: + val_int = config_get_int(config_device->name, config->name, config->default_int); + if (val_int > config->spinner.max) + val_int = config->spinner.max; + else if (val_int < config->spinner.min) + val_int = config->spinner.min; + + SendMessage(h, WM_GETTEXT, 79, (LPARAM)s); + sscanf(s, "%i", &c); + + if (val_int != c) + changed = 1; + + id += 2; + break; + case CONFIG_HEX16: val_int = config_get_hex16(config_device->name, config->name, config->default_int); @@ -218,16 +265,16 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam return TRUE; } - ret = msgbox_reset(ghwnd); - switch(ret) - { - case IDNO: - EndDialog(hdlg, 0); - return TRUE; - case IDCANCEL: - return FALSE; - default: - break; + ret = msgbox_reset(ghwnd); + switch(ret) + { + case IDNO: + EndDialog(hdlg, 0); + return TRUE; + case IDCANCEL: + return FALSE; + default: + break; } id = IDC_CONFIG_BASE; @@ -262,6 +309,27 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam id += 2; break; + case CONFIG_FILE: + SendMessage(h, WM_GETTEXT, 511, (LPARAM)s); + + config_set_string(config_device->name, config->name, s); + + id += 3; + break; + + case CONFIG_SPINNER: + SendMessage(h, WM_GETTEXT, 79, (LPARAM)s); + sscanf(s, "%i", &c); + if (c > config->spinner.max) + c = config->spinner.max; + else if (c < config->spinner.min) + c = config->spinner.min; + + config_set_int(config_device->name, config->name, c); + + id += 2; + break; + case CONFIG_HEX16: c = SendMessage(h, CB_GETCURSEL, 0, 0); for (; c > 0; c--) @@ -289,12 +357,90 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam EndDialog(hdlg, 0); return TRUE; - } - case IDCANCEL: - EndDialog(hdlg, 0); - return TRUE; - } - break; + } + else if (cid == IDCANCEL) + { + EndDialog(hdlg, 0); + return TRUE; + } + else + { + int id = IDC_CONFIG_BASE; + device_config_t *config = config_device->config; + + while (config->type != -1) + { + switch (config->type) + { + case CONFIG_BINARY: + id++; + break; + + case CONFIG_SELECTION: + case CONFIG_MIDI: + case CONFIG_SPINNER: + id += 2; + break; + + case CONFIG_FILE: + { + if (cid == id+1) + { + char s[512]; + s[0] = 0; + int c, d; + HWND h = GetDlgItem(hdlg, id); + SendMessage(h, WM_GETTEXT, 511, (LPARAM)s); + char file_filter[512]; + file_filter[0] = 0; + + c = 0; + while (config->file_filter[c].description[0]) + { + if (c > 0) + strcat(file_filter, "|"); + strcat(file_filter, config->file_filter[c].description); + strcat(file_filter, " ("); + d = 0; + while (config->file_filter[c].extensions[d][0]) + { + if (d > 0) + strcat(file_filter, ";"); + strcat(file_filter, "*."); + strcat(file_filter, config->file_filter[c].extensions[d]); + d++; + } + strcat(file_filter, ")|"); + d = 0; + while (config->file_filter[c].extensions[d][0]) + { + if (d > 0) + strcat(file_filter, ";"); + strcat(file_filter, "*."); + strcat(file_filter, config->file_filter[c].extensions[d]); + d++; + } + c++; + } + strcat(file_filter, "|All files (*.*)|*.*|"); + d = strlen(file_filter); + + /* replace | with \0 */ + for (c = 0; c < d; ++c) + if (file_filter[c] == '|') + file_filter[c] = '\0'; + + if (!file_dlg_mb(hdlg, file_filter, s, 0)) + SendMessage(h, WM_SETTEXT, 0, (LPARAM)openfilestring); + } + } + break; + } + config++; + } + } + } + break; } return FALSE; } @@ -402,6 +548,122 @@ void deviceconfig_open(HWND hwnd, device_t *device) y += 20; break; + + case CONFIG_SPINNER: + /*Spinner*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 140; + item->cy = 14; + + item->style = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER; + item->dwExtendedStyle = WS_EX_CLIENTEDGE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0081; /* edit text class */ + + data += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t)data) & 2) + data++; + + /* TODO: add up down class */ + /*Static text*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ + + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t)data) & 2) + data++; + + y += 20; + break; + + case CONFIG_FILE: + /*File*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 100; + item->cy = 14; + + item->style = WS_CHILD | WS_VISIBLE | ES_READONLY; + item->dwExtendedStyle = WS_EX_CLIENTEDGE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0081; /* edit text class */ + + data += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t)data) & 2) + data++; + + /* Button */ + item = (DLGITEMTEMPLATE *)data; + item->x = 175; + item->y = y; + item->id = id++; + + item->cx = 35; + item->cy = 14; + + item->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; /* button class */ + + data += MultiByteToWideChar(CP_ACP, 0, "Browse", -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t)data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ + + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t)data) & 2) + data++; + + y += 20; + break; } if (((unsigned long)data) & 2) diff --git a/src/WIN/win_language.c b/src/WIN/win_language.c index e2bf2b24a..4b83261ce 100644 --- a/src/WIN/win_language.c +++ b/src/WIN/win_language.c @@ -313,6 +313,15 @@ int file_dlg(HWND hwnd, WCHAR *f, char *fn, int save) return file_dlg_w(hwnd, f, ufn, save); } +int file_dlg_mb(HWND hwnd, char *f, char *fn, int save) +{ + WCHAR uf[512]; + WCHAR ufn[512]; + mbstowcs(uf, f, strlen(fn) + 1); + mbstowcs(ufn, fn, strlen(fn) + 1); + return file_dlg_w(hwnd, uf, ufn, save); +} + int file_dlg_w_st(HWND hwnd, int i, WCHAR *fn, int save) { return file_dlg_w(hwnd, win_language_get_string_from_id(i), fn, save); diff --git a/src/WIN/win_language.h b/src/WIN/win_language.h index 50b0105e3..053eabf0d 100644 --- a/src/WIN/win_language.h +++ b/src/WIN/win_language.h @@ -34,6 +34,7 @@ void msgbox_critical(HWND hwndParent, int i); int file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save); int file_dlg(HWND hwnd, WCHAR *f, char *fn, int save); +int file_dlg_mb(HWND hwnd, char *f, char *fn, int save); int file_dlg_w_st(HWND hwnd, int i, WCHAR *fn, int save); int file_dlg_st(HWND hwnd, int i, char *fn, int save); diff --git a/src/device.h b/src/device.h index 087c3464d..8948551fd 100644 --- a/src/device.h +++ b/src/device.h @@ -25,9 +25,11 @@ #define CONFIG_BINARY 2 #define CONFIG_SELECTION 3 #define CONFIG_MIDI 4 -#define CONFIG_HEX16 5 -#define CONFIG_HEX20 6 -#define CONFIG_MAC 7 +#define CONFIG_FILE 5 +#define CONFIG_SPINNER 6 +#define CONFIG_HEX16 7 +#define CONFIG_HEX20 8 +#define CONFIG_MAC 9 enum @@ -46,6 +48,19 @@ typedef struct device_config_selection_t int value; } device_config_selection_t; +typedef struct device_config_file_filter_t +{ + char description[256]; + char extensions[25][25]; +} device_config_file_filter_t; + +typedef struct device_config_spinner_t +{ + int min; + int max; + int step; +} device_config_spinner_t; + typedef struct device_config_t { char name[256]; @@ -54,6 +69,8 @@ typedef struct device_config_t char default_string[256]; int default_int; device_config_selection_t selection[16]; + device_config_file_filter_t file_filter[16]; + device_config_spinner_t spinner; } device_config_t; typedef struct device_t From 3b056733e7f6d3d050ec6a585f7f7bbb1d12d1d7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Aug 2017 22:59:44 +0200 Subject: [PATCH 64/82] Committed src/SOUND/midi_fluidsynth.c/h that I forgot to commit before. --- src/SOUND/midi_fluidsynth.c | 435 ++++++++++++++++++++++++++++++++++++ src/SOUND/midi_fluidsynth.h | 1 + 2 files changed, 436 insertions(+) create mode 100644 src/SOUND/midi_fluidsynth.c create mode 100644 src/SOUND/midi_fluidsynth.h diff --git a/src/SOUND/midi_fluidsynth.c b/src/SOUND/midi_fluidsynth.c new file mode 100644 index 000000000..4d147aef4 --- /dev/null +++ b/src/SOUND/midi_fluidsynth.c @@ -0,0 +1,435 @@ +/* some code borrowed from scummvm */ + +#include +#include +#include +#include +#include "../config.h" +#include "../WIN/plat_thread.h" +#include "../device.h" +#include "midi_fluidsynth.h" +#include "midi.h" +#include "sound.h" + +#define RENDER_RATE 30 + +extern void givealbuffer_midi(void *buf, uint32_t size); +extern void pclog(const char *format, ...); +extern void al_set_midi(int freq, int buf_size); +extern int soundon; + +typedef struct fluidsynth_t +{ + fluid_settings_t* settings; + fluid_synth_t* synth; + int samplerate; + int sound_font; + + thread_t* thread_h; + event_t* event; + int buf_size; + float* buffer; + int16_t* buffer_int16; + int midi_pos; + +} fluidsynth_t; + +fluidsynth_t fsdev; + +int fluidsynth_available() +{ + return 1; +} + +void fluidsynth_poll() +{ + fluidsynth_t* data = &fsdev; + data->midi_pos++; + if (data->midi_pos == 48000/RENDER_RATE) + { + data->midi_pos = 0; + thread_set_event(data->event); + } +} + +static void fluidsynth_thread(void *param) +{ + fluidsynth_t* data = (fluidsynth_t*)param; + while (1) + { + thread_wait_event(data->event, -1); + if (sound_is_float) + { + memset(data->buffer, 0, data->buf_size * sizeof(float)); + if (data->synth) + fluid_synth_write_float(data->synth, data->buf_size/2, data->buffer, 0, 2, data->buffer, 1, 2); + if (soundon) + givealbuffer_midi(data->buffer, data->buf_size); + } + else + { + memset(data->buffer, 0, data->buf_size * sizeof(int16_t)); + if (data->synth) + fluid_synth_write_s16(data->synth, data->buf_size/2, data->buffer_int16, 0, 2, data->buffer_int16, 1, 2); + if (soundon) + givealbuffer_midi(data->buffer_int16, data->buf_size); + } + } +} + +void fluidsynth_msg(uint8_t *msg) +{ + fluidsynth_t* data = &fsdev; + + uint32_t val = *((uint32_t*)msg); + + uint32_t param2 = (uint8_t) ((val >> 16) & 0xFF); + uint32_t param1 = (uint8_t) ((val >> 8) & 0xFF); + uint8_t cmd = (uint8_t) (val & 0xF0); + uint8_t chan = (uint8_t) (val & 0x0F); + + switch (cmd) { + case 0x80: /* Note Off */ + fluid_synth_noteoff(data->synth, chan, param1); + break; + case 0x90: /* Note On */ + fluid_synth_noteon(data->synth, chan, param1, param2); + break; + case 0xA0: /* Aftertouch */ + break; + case 0xB0: /* Control Change */ + fluid_synth_cc(data->synth, chan, param1, param2); + break; + case 0xC0: /* Program Change */ + fluid_synth_program_change(data->synth, chan, param1); + break; + case 0xD0: /* Channel Pressure */ + break; + case 0xE0: /* Pitch Bend */ + fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1); + break; + case 0xF0: /* SysEx */ + break; + default: + pclog("fluidsynth: unknown send() command 0x%02X", cmd); + break; + } +} + +void fluidsynth_sysex(uint8_t* data, unsigned int len) +{ + fluidsynth_t* d = &fsdev; + + fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); +} + +void* fluidsynth_init() +{ + fluidsynth_t* data = &fsdev; + memset(data, 0, sizeof(fluidsynth_t)); + + data->settings = new_fluid_settings(); + + fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); + fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain")/100.0f); + + data->synth = new_fluid_synth(data->settings); + + char* sound_font = device_get_config_string("sound_font"); + data->sound_font = fluid_synth_sfload(data->synth, sound_font, 1); + + if (device_get_config_int("chorus")) + { + fluid_synth_set_chorus_on(data->synth, 1); + + int chorus_voices = device_get_config_int("chorus_voices"); + double chorus_level = device_get_config_int("chorus_level") / 100.0; + double chorus_speed = device_get_config_int("chorus_speed") / 100.0; + double chorus_depth = device_get_config_int("chorus_depth") / 10.0; + + int chorus_waveform = FLUID_CHORUS_MOD_SINE; + if (device_get_config_int("chorus_waveform") == 0) + chorus_waveform = FLUID_CHORUS_MOD_SINE; + else + chorus_waveform = FLUID_CHORUS_MOD_TRIANGLE; + + fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); + } + else + fluid_synth_set_chorus_on(data->synth, 0); + + if (device_get_config_int("reverb")) + { + fluid_synth_set_reverb_on(data->synth, 1); + + double reverb_room_size = device_get_config_int("reverb_room_size") / 100.0; + double reverb_damping = device_get_config_int("reverb_damping") / 100.0; + int reverb_width = device_get_config_int("reverb_width"); + double reverb_level = device_get_config_int("reverb_level") / 100.0; + + fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); + } + else + fluid_synth_set_reverb_on(data->synth, 0); + + int interpolation = device_get_config_int("interpolation"); + int fs_interpolation = FLUID_INTERP_4THORDER; + + if (interpolation == 0) + fs_interpolation = FLUID_INTERP_NONE; + else if (interpolation == 1) + fs_interpolation = FLUID_INTERP_LINEAR; + else if (interpolation == 2) + fs_interpolation = FLUID_INTERP_4THORDER; + else if (interpolation == 3) + fs_interpolation = FLUID_INTERP_7THORDER; + + fluid_synth_set_interp_method(data->synth, -1, fs_interpolation); + + double samplerate; + fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); + data->samplerate = (int)samplerate; + data->buf_size = data->samplerate/RENDER_RATE*2; + if (sound_is_float) + { + data->buffer = malloc(data->buf_size * sizeof(float)); + data->buffer_int16 = NULL; + } + else + { + data->buffer = NULL; + data->buffer_int16 = malloc(data->buf_size * sizeof(int16_t)); + } + data->event = thread_create_event(); + data->thread_h = thread_create(fluidsynth_thread, data); + + al_set_midi(data->samplerate, data->buf_size); + + pclog("fluidsynth (%s) initialized, samplerate %d, buf_size %d\n", fluid_version_str(), data->samplerate, data->buf_size); + + midi_device_t* dev = malloc(sizeof(midi_device_t)); + memset(dev, 0, sizeof(midi_device_t)); + + dev->play_msg = fluidsynth_msg; + dev->play_sysex = fluidsynth_sysex; + dev->poll = fluidsynth_poll; + + midi_init(dev); + + return dev; +} + +void fluidsynth_close(void* p) +{ + if (!p) return; + + fluidsynth_t* data = &fsdev; + + if (data->sound_font != -1) + fluid_synth_sfunload(data->synth, data->sound_font, 1); + delete_fluid_synth(data->synth); + delete_fluid_settings(data->settings); + + midi_close(); + + if (data->buffer) + { + free(data->buffer); + } + + if (data->buffer_int16) + { + free(data->buffer_int16); + } + + pclog("fluidsynth closed\n"); +} + +static device_config_t fluidsynth_config[] = +{ + { + .name = "sound_font", + .description = "Sound Font", + .type = CONFIG_FILE, + .default_string = "", + .file_filter = + { + { + .description = "SF2 Sound Fonts", + .extensions = + { + "sf2" + } + } + } + }, + { + .name = "output_gain", + .description = "Output Gain", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 100 + }, + .default_int = 100 + }, + { + .name = "chorus", + .description = "Chorus", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "chorus_voices", + .description = "Chorus Voices", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 99 + }, + .default_int = 3 + }, + { + .name = "chorus_level", + .description = "Chorus Level", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 100 + }, + .default_int = 100 + }, + { + .name = "chorus_speed", + .description = "Chorus Speed", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 30, + .max = 500 + }, + .default_int = 30 + }, + { + .name = "chorus_depth", + .description = "Chorus Depth", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 210 + }, + .default_int = 80 + }, + { + .name = "chorus_waveform", + .description = "Chorus Waveform", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "Sine", + .value = 0 + }, + { + .description = "Triangle", + .value = 1 + } + }, + .default_int = 0 + }, + { + .name = "reverb", + .description = "Reverb", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "reverb_room_size", + .description = "Reverb Room Size", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 120 + }, + .default_int = 20 + }, + { + .name = "reverb_damping", + .description = "Reverb Damping", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 100 + }, + .default_int = 0 + }, + { + .name = "reverb_width", + .description = "Reverb Width", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 100 + }, + .default_int = 1 + }, + { + .name = "reverb_level", + .description = "Reverb Level", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 100 + }, + .default_int = 90 + }, + { + .name = "interpolation", + .description = "Interpolation Method", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "None", + .value = 0 + }, + { + .description = "Linear", + .value = 1 + }, + { + .description = "4th Order", + .value = 2 + }, + { + .description = "7th Order", + .value = 3 + } + }, + .default_int = 2 + }, + { + .type = -1 + } +}; + +device_t fluidsynth_device = +{ + "FluidSynth", + 0, + fluidsynth_init, + fluidsynth_close, + fluidsynth_available, + NULL, + NULL, + NULL, + fluidsynth_config +}; diff --git a/src/SOUND/midi_fluidsynth.h b/src/SOUND/midi_fluidsynth.h new file mode 100644 index 000000000..1daeb29c0 --- /dev/null +++ b/src/SOUND/midi_fluidsynth.h @@ -0,0 +1 @@ +extern device_t fluidsynth_device; From 4b5be4f2f6b750c4496ab087b1342b808cc92b4c Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 8 Aug 2017 16:14:50 +0200 Subject: [PATCH 65/82] The fluidsynth .DLL are now dynamically loaded like PCap, the emulator can now even when said .DLL is not present; Fixed a tiny bug in the Cirrus Logic blitter; Adding DEV_BRANCH=y parameter to make now compiles the Cirrus Logic emulation code *and* the Nvidia Riva emulation code; The Sierra SC1502x RAMDAC emulation code is now correctly named as such; The makefile now knows the dependencies for a lot more files (with the unfortunate effect that 86Box.exe is now 8 MB after stripping); win_setting.c no longer includes scsi_buslogic.c - that was a leftover of long gone code. --- src/Makefile.mingw | 277 +++++++++++++++++- src/SOUND/midi_fluidsynth.c | 119 ++++++-- src/VIDEO/vid_cl_gd_blit.c | 4 +- src/VIDEO/vid_et4000.c | 8 +- src/VIDEO/vid_paradise.c | 1 - ...{vid_unk_ramdac.c => vid_sc1502x_ramdac.c} | 6 +- src/VIDEO/vid_sc1502x_ramdac.h | 11 + src/VIDEO/vid_unk_ramdac.h | 11 - src/WIN/86Box.rc | 1 + src/WIN/plat_ui.h | 12 +- src/WIN/resource.h | 3 +- src/WIN/win_deviceconfig.c | 12 +- src/WIN/win_settings.c | 1 - 13 files changed, 395 insertions(+), 71 deletions(-) rename src/VIDEO/{vid_unk_ramdac.c => vid_sc1502x_ramdac.c} (93%) create mode 100644 src/VIDEO/vid_sc1502x_ramdac.h delete mode 100644 src/VIDEO/vid_unk_ramdac.h diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 8c34794bb..f51f57530 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -8,7 +8,7 @@ # # Modified Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.32 2017/07/27 +# Version: @(#)Makefile.mingw 1.0.33 2017/08/08 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -127,8 +127,19 @@ endif ifeq ($(X64), y) PLATCG = codegen_x86-64.o +CGOPS = codegen_ops_x86-64.h +VCG = vid_voodoo_codegen_x86-64.h else PLATCG = codegen_x86.o +CGOPS = codegen_ops_x86.h +VCG = vid_voodoo_codegen_x86.h +endif + + +ifeq ($(DEV_BRANCH), y) +DBFLAGS = -DDEV_BRANCH +else +DBFLAGS = endif @@ -233,9 +244,9 @@ VIDOBJ = video.o \ vid_ati_eeprom.o vid_ati18800.o vid_ati28800.o \ vid_ati68860_ramdac.o vid_ati_mach64.o \ vid_ics2595.o \ + vid_sc1502x_ramdac.o \ vid_sdac_ramdac.o \ vid_stg_ramdac.o \ - vid_unk_ramdac.o \ vid_wy700.o \ vid_voodoo.o \ vid_pcjr.o vid_ps1_svga.o \ @@ -250,8 +261,9 @@ WINOBJ = win.o \ win_iodev.o win_joystick.o win_midi.o \ win_settings.o win_deviceconfig.o win_joystickconfig.o \ 86Box.res -ifdef DEV_BRANCH -DEVBRANCHOBJ = vid_nv_riva128.o +ifeq ($(DEV_BRANCH), y) +DEVBRANCHOBJ = vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o \ + vid_nv_riva128.o endif OBJ = $(MAINOBJ) $(CPUOBJ) $(SYSOBJ) $(DEVOBJ) $(USBOBJ) \ $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) $(WINOBJ) \ @@ -263,7 +275,7 @@ LIBS = -mwindows \ -lopenal.dll \ -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ -lcomctl32 -lkernel32 -lwsock32 -lwinmm -liphlpapi -lpsapi \ - -static -lstdc++ -lgcc -lfluidsynth -lfluidsynth.dll + -static -lstdc++ -lgcc # Build rules. @@ -313,9 +325,9 @@ pcap_if.res: pcap_if.rc # Module dependencies. -acer386sx.o: ibm.h cpu/cpu.h io.h device.h model.h -acerm3a.o: ibm.h cpu/cpu.h io.h device.h model.h +# / +acer386sx.o: ibm.h cpu/cpu.h io.h device.h model.h ali1429.o: ibm.h cpu/cpu.h io.h mem.h device.h model.h @@ -326,6 +338,10 @@ bugger.o: ibm.h io.h bugger.h cdrom.o: 86box.h cdrom.h ibm.h ide.h piix.h scsi.h timer.h \ win/plat_iodev.h +cdrom_dosbox.o: cdrom_dosbox.h + +cdrom_image.o: config.h cdrom_dosbox.h cdrom.h cdrom_image.h cdrom_null.h + cdrom_ioctl.o: ibm.h cdrom.h cdrom_ioctl.h scsi.h cdrom_null.o: ibm.h cdrom.h cdrom_ioctl.h @@ -337,7 +353,7 @@ config.o: cdrom.h config.h device.h disc.h fdc.h fdd.h ibm.h \ network/network.h nvr.h scsi.h win/plat_joystick.h \ win/plat_midi.h sound/snd_dbopl.h sound/snd_mpu401.h \ sound/snd_opl.h sound/sound.h video/video.h win/win.h \ - win/win_language.h + win/resource.h win/win_language.h device.o: ibm.h cpu/cpu.h config.h device.h model.h sound/sound.h @@ -357,6 +373,9 @@ disc_td0.o: ibm.h disc.h disc_td0.h fdc.h fdd.h dma.o: ibm.h cpu/x86.h mem.h io.h dma.h +esdi_at.o: ibm.h device.h hdd_image.h io.h mem.h pic.h rom.h timer.h \ + esdi_at.h + fdc.o: ibm.h disc.h dma.h fdc.h fdd.h io.h pic.h timer.h fdc37c665.o: ibm.h disc.h fdc.h fdd.h ide.h io.h lpt.h serial.h \ @@ -374,8 +393,8 @@ gameport.o: ibm.h cpu/cpu.h device.h io.h timer.h gameport.h \ joystick_ch_flightstick_pro.h joystick_standard.h \ joystick_sw_pad.h joystick_tm_fcs.h plat_joystick.h -hdd.o: ibm.h cpu/cpu.h device.h hdd.h model.h hdd_esdi.h \ - mfm_at.h mfm_xebec.h xtide.h +hdd.o: ibm.h cpu/cpu.h device.h hdd.h model.h esdi_at.h \ + hdd_esdi.h mfm_at.h mfm_xebec.h xtide.h hdd_image.o: ibm.h ide.h hdd_image.h @@ -396,8 +415,6 @@ i430vx.o: ibm.h cpu/cpu.h io.h mem.h pci.h device.h model.h i440fx.o: ibm.h cpu/cpu.h io.h mem.h pci.h device.h model.h -i82335.o: ibm.h io.h mem.h - ide.o: 86box.h cdrom.h hdd_image.h ibm.h io.h pic.h timer.h cdrom.h scsi.h ide.h intel.o: ibm.h cpu/cpu.h io.h mem.h pit.h timer.h intel.h @@ -458,7 +475,7 @@ mfm_xebec.o: ibm.h device.h dma.h hdd_image.h io.h mem.h pic.h rom.h timer.h mfm model.o: ibm.h io.h mem.h rom.h device.h model.h cpu/cpu.h \ mouse.h cdrom.h disc.h dma.h fdc.h \ fdc37c665.h fdc37c669.h fdc37c932fr.h \ - gameport.h i82335.h ide.h intel.h intel_flash.h \ + gameport.h ide.h intel.h intel_flash.h \ keyboard_amstrad.h keyboard_at.h keyboard_olim24.h \ keyboard_pcjr.h keyboard_xt.h lpt.h mem.h memregs.h \ nmi.h nvr.h pc87306.h pci.h pic.h piix.h pit.h ps2_mca.h \ @@ -469,7 +486,7 @@ model.o: ibm.h io.h mem.h rom.h device.h model.h cpu/cpu.h \ mouse.o: ibm.h cpu/cpu.h device.h model.h mouse.h keyboard_olim24.h -mouse_bus.o: ibm.h io.h pic.h mouse.h +mouse_bus.o: ibm.h io.h pic.h timer.h mouse.h mouse_ps2.o: ibm.h keyboard_at.h mouse.h plat_mouse.h @@ -540,6 +557,8 @@ scsi_disk.o: 86box.h cdrom.h hdd_image.h ibm.h ide.h piix.h scsi.h \ serial.o: ibm.h io.h pic.h timer.h serial.h plat_serial.h +serial_old.o: ibm.h io.h mouse.h pic.h serial.h timer.h + sio.o: ibm.h cdrom.h disc.h dma.h fdc.h keyboard_at.h ide.h \ io.h mem.h pci.h sio.h @@ -549,6 +568,8 @@ sis50x.o: ibm.h device.h io.h mem.h pci.h sis50x.h sis85c471.o: ibm.h ide.h disc.h fdc.h fdd.h io.h lpt.h serial.h sis85c471.h +superio_detect.o: ibm.h io.h disc.h fdd.h fdc.h superio_detect.h + tandy_eeprom.o: ibm.h device.h mem.h io.h rom.h tandy_eeprom.h tandy_rom.o: ibm.h device.h io.h mem.h rom.h tandy_rom.h @@ -563,5 +584,233 @@ wd76c10.o: ibm.h disc.h fdc.h io.h mem.h serial.h wd76c10.h xtide.o: ibm.h io.h mem.h rom.h device.h ide.h xtide.h +# cpu/ +386.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87.h mem.h disc.h fdc.h pic.h timer.h cpu/386_common.h + +386_dynarec.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_ops.h cpu/x87.h mem.h cpu/codegen.h disc.h fdc.h pic.h timer.h cpu/386_common.h \ + cpu/x86_ops.h cpu/x86seg.h cpu/x86_ops_arith.h cpu/x86_ops_atomic.h cpu/x86_ops_bcd.h cpu/x86_ops_bit.h \ + cpu/x86_ops_bitscan.h cpu/x86_ops_call.h cpu/x86_ops_flag.h cpu/x86_ops_fpu.h cpu/x86_ops_inc_dec.h cpu/x86_ops_int.h \ + cpu/x86_ops_io.h cpu/x86_ops_jump.h cpu/x86_ops_misc.h \ + cpu/x87_ops_arith.h cpu/x87_ops_misc.h cpu/x87_ops_loadstore.h \ + cpu/x87_ops.h cpu/x86_ops_i686.h cpu/x86_ops_mmx.h \ + cpu/x86_ops_mmx_arith.h cpu/x86_ops_mmx_cmp.h cpu/x86_ops_mmx_logic.h cpu/x86_ops_mmx_pack.h cpu/x86_ops_mmx_shift.h \ + cpu/x86_ops_mov.h cpu/x86_ops_mov_ctrl.h cpu/x86_ops_mov_seg.h cpu/x86_ops_movx.h cpu/x86_ops_msr.h cpu/x86_ops_mul.h \ + cpu/x86_ops_pmode.h cpu/x86_ops_prefix.h cpu/x86_ops_rep.h cpu/x86_ops_ret.h cpu/x86_ops_set.h cpu/x86_ops_shift.h \ + cpu/x86_ops_stack.h cpu/x86_ops_string.h cpu/x86_ops_xchg.h \ + cpu/386_ops.h + +386_dynarec_ops.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_ops.h cpu/x87.h cpu/x86_flags.h mem.h cpu/codegen.h pic.h cpu/386_common.h \ + cpu/x86_ops.h cpu/x86seg.h cpu/x86_ops_arith.h cpu/x86_ops_atomic.h cpu/x86_ops_bcd.h cpu/x86_ops_bit.h \ + cpu/x86_ops_bitscan.h cpu/x86_ops_call.h cpu/x86_ops_flag.h cpu/x86_ops_fpu.h cpu/x86_ops_inc_dec.h cpu/x86_ops_int.h \ + cpu/x86_ops_io.h cpu/x86_ops_jump.h cpu/x86_ops_misc.h \ + cpu/x87_ops_arith.h cpu/x87_ops_misc.h cpu/x87_ops_loadstore.h \ + cpu/x87_ops.h cpu/x86_ops_i686.h cpu/x86_ops_mmx.h \ + cpu/x86_ops_mmx_arith.h cpu/x86_ops_mmx_cmp.h cpu/x86_ops_mmx_logic.h cpu/x86_ops_mmx_pack.h cpu/x86_ops_mmx_shift.h \ + cpu/x86_ops_mov.h cpu/x86_ops_mov_ctrl.h cpu/x86_ops_mov_seg.h cpu/x86_ops_movx.h cpu/x86_ops_msr.h cpu/x86_ops_mul.h \ + cpu/x86_ops_pmode.h cpu/x86_ops_prefix.h cpu/x86_ops_rep.h cpu/x86_ops_ret.h cpu/x86_ops_set.h cpu/x86_ops_shift.h \ + cpu/x86_ops_stack.h cpu/x86_ops_string.h cpu/x86_ops_xchg.h \ + cpu/386_ops.h + +808x.o: ibm.h cpu/cpu.h cpu/x86.h keyboard.h mem.h nmi.h pic.h scsi.h timer.h + +codegen.o: ibm.h cpu/x86_ops.h mem.h cpu/codegen.h + +codegen_ops.o: ibm.h mem.h cpu/x86.h cpu/x86_ops.h cpu/x86_flags.h cpu/x87.h cpu/386_common.h cpu/cpu.h cpu/codegen.h cpu/codegen_ops.h \ + cpu/$(CGOPS) cpu/codegen_ops_arith.h cpu/codegen_ops_fpu.h cpu/codegen_ops_jump.h cpu/codegen_ops_logic.h cpu/codegen_ops_misc.h \ + cpu/codegen_ops_mmx.h cpu/codegen_ops_mov.h cpu/codegen_ops_shift.h cpu/codegen_ops_stack.h cpu/codegen_ops_xchg.h + +codegen_timing_486.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h + +codegen_timing_686.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_timing_common.h + +codegen_timing_common.o: ibm.h cpu/codegen_timing_common.h + +codegen_timing_pentium.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h + +codegen_timing_winchip.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h + +codegen_x86.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h mem.h cpu/386_common.h cpu/codegen.h cpu/codegen_ops.h \ + cpu/codegen_ops_x86.h + +codegen_x86-64.o: ibm.h mem.h cpu/cpu.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h cpu/386_common.h cpu/codegen.h cpu/codegen_ops.h \ + cpu/codegen_ops_x86-64.h + +cpu.o: ibm.h cpu/cpu.h device.h model.h io.h cpu/x86_ops.h mem.h pci.h cpu/codegen.h + +x86seg.o: ibm.h mem.h nvr.h cpu/x86.h cpu/386.h cpu/386_common.h cpu/cpu.h + +x87.o: ibm.h pic.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h cpu/386_common.h + +# network/ +net_ne2000.o: ibm.h io.h mem.h rom.h pci.h pic.h device.h config.h disc_random.h network/network.h network/net_ne2000.h network/bswap.h + +net_pcap.o: ibm.h config.h device.h network/network.h win/plat_dynld.h win/plat_thread.h + +net_slirp.o: network/slirp/slirp.h network/slirp/queue.h ibm.h config.h device.h network/network.h win/plat_thread.h + +network.o: ibm.h device.h network/network.h network/net_ne2000.h win/plat_ui.h + +# video/ +vid_ati_eeprom.o: ibm.h mem.h rom.h video/vid_ati_eeprom.h + +vid_ati_mach64.o: ibm.h device.h io.h mem.h pci.h rom.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_svga_render.h \ + video/vid_ati68860_ramdac.h video/vid_ati_eeprom.h video/vid_ics2595.h + +vid_ati18800.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_ati18800.h video/vid_ati_eeprom.h video/vid_svga.h + +vid_ati28800.o: ibm.h io.h mem.h rom.h device.h timer.h video/video.h video/vid_ati28800.h video/vid_ati_eeprom.h video/vid_svga.h \ + video/vid_svga_render.h + +vid_ati68860_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_ati68860_ramdac.h video/vid_svga_render.h + +vid_cga.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_cga_comp.h win/win_cgapal.h + +vid_cga_comp.o: ibm.h device.h mem.h video/vid_cga.h video/vid_cga_comp.h + +vid_cl_gd.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_cl_ramdac.h \ + video/vid_cl_gd.h video/vid_cl_gd_blit.h + +vid_cl_gd_blit.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_cl_ramdac.h \ + video/vid_cl_gd.h video/vid_cl_gd_blit.h video/vid_cl_gd_vga_rop.h + +vid_cl_gd_ramdac.o: ibm.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_cl_ramdac.h video/vid_cl_gd.h \ + video/vid_cl_gd_blit.h + +vid_colorplus.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_colorplus.h video/vid_cga_comp.h + +vid_ega.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_ega.h video/vid_ega_render.h + +vid_ega_render.o: ibm.h device.h mem.h rom.h video/video.h video/vid_ega.h video/vid_ega_render.h + +vid_et4000.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_sc1502x_ramdac.h video/vid_et4000.h + +vid_et4000w32.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_icd2061.h \ + video/vid_stg_ramdac.h + +vid_genius.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_genius.h + +vid_hercules.o: ibm.h mem.h io.h timer.h device.h video/video.h video/vid_hercules.h win/win_cgapal.h + +vid_herculesplus.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_herculesplus.h + +vid_icd2061.o: ibm.h video/vid_icd2061.h + +vid_ics2595.o: ibm.h video/vid_ics2595.h + +vid_incolor.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_incolor.h + +vid_mda.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_mda.h win/win_cgapal.h + +vid_nv_riva128.o: ibm.h io.h mem.h pci.h pic.h rom.h timer.h device.h win/plat_thread.h video/video.h video/vid_svga.h \ + video/vid_svga_render.h + +vid_olivetti_m24.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_olivetti_m24.h + +vid_oti067.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_oti067.h video/vid_svga.h + +vid_paradise.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_paradise.h video/vid_svga.h video/vid_svga_render.h + +vid_pc200.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_pc200.h + +vid_pc1512.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_pc1512.h + +vid_pc1640.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_cga.h video/vid_ega.h video/vid_pc1640.h + +vid_pcjr.o: ibm.h io.h mem.h pic.h timer.h device.h video/video.h video/vid_cga_comp.h video/vid_pcjr.h + +vid_ps1_svga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_vga.h + +vid_s3.o: ibm.h device.h io.h mem.h pci.h rom.h win/plat_thread.h video/video.h video/vid_s3.h video/vid_svga.h \ + video/vid_svga_render.h video/vid_sdac_ramdac.h + +vid_s3_virge.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_s3_virge.h video/vid_svga.h \ + video/vid_svga_render.h + +vid_sc1502x_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_sc1502x_ramdac.h + +vid_sdac_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_sdac_ramdac.h + +vid_stg_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_stg_ramdac.h + +vid_svga.o: ibm.h io.h mem.h rom.h timer.h video/video.h video/vid_svga.h video/vid_svga_render.h + +vid_svga_render.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_svga_render.h + +vid_tandy.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_tandy.h video/vid_cga_comp.h + +vid_tandysl.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_tandysl.h + +vid_tgui9440.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_svga_render.h \ + video/vid_tkd8001_ramdac.h video/vid_tgui9440.h + +vid_tkd8001_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_tkd8001_ramdac.h + +vid_tvga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_tkd8001_ramdac.h \ + video/vid_tvga.h + +vid_vga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_vga.h + +vid_voodoo.o: ibm.h cpu/cpu.h mem.h rom.h pci.h timer.h device.h win/plat_thread.h video/video.h video/vid_svga.h \ + video/vid_voodoo.h video/vid_voodoo_dither.h video/$(VCG) + +vid_wy700.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_wy700.h + +video.o: ibm.h cpu/cpu.h io.h mem.h rom.h config.h device.h timer.h win/plat_thread.h video/video.h video/vid_svga.h \ + win/resource.h win/win.h win/win_cgapal.h \ + video/vid_ati18800.h video/vid_ati28800.h video/vid_ati_mach64.h video/vid_cga.h \ + video/vid_cl_ramdac.h video/vid_cl_gd.h \ + video/vid_ega.h video/vid_et4000.h video/vid_et4000w32.h video/vid_genius.h video/vid_hercules.h \ + video/vid_herculesplus.h video/vid_incolor.h video/vid_colorplus.h video/vid_mda.h \ + video/vid_nv_riva128.h \ + video/vid_olivetti_m24.h video/vid_oti067.h video/vid_paradise.h video/vid_pc1512.h video/vid_pc1640.h \ + video/vid_pc200.h video/vid_pcjr.h video/vid_ps1_svga.h video/vid_s3.h video/vid_s3_virge.h video/vid_tandy.h \ + video/vid_tandysl.h video/vid_tgui9440.h video/vid_tvga.h video/vid_vga.h video/vid_wy700.h + +# win/ +win.o: 86box.h device.h disc.h fdd.h hdd.h ibm.h cpu/cpu.h mem.h rom.h nvr.h config.h model.h ide.h cdrom.h cdrom_null.h \ + cdrom_ioctl.h cdrom_image.h scsi.h scsi_disk.h video/video.h video/vid_ega.h mouse.h sound/sound.h sound/snd_dbopl.h \ + win/plat_keyboard.h win/plat_iodev.h win/plat_mouse.h win/plat_midi.h win/plat_thread.h win/plat_ticks.h win/plat_ui.h \ + win/resource.h win/win.h win/win_cgapal.h win/win_ddraw.h win/win_d3d.h win/win_language.h + +win_d3d.o: video/video.h win/win.h win/resource.h win/win_d3d.h win/win_cgapal.h + +win_d3d_fs.o: 86box.h video/video.h win/win.h win/resource.h win/win_d3d.h win/win_cgapal.h + +win_ddraw.o: video/video.h win/resource.h win/win_ddraw.h win/win_cgapal.h + +win_ddraw_fs.o: video/video.h win/resource.h win/win_ddraw.h win/win_cgapal.h + +win_ddraw_screenshot.o: video/video.h win/resource.h win/win.h win/win_ddraw.h win/win_language.h + +win_deviceconfig.o: win/plat_midi.h win/resource.h win/win.h win/win_language.h + +win_dynld.o: win/plat_dynld.h win/resource.h ibm.h + +win_iodev.o: ibm.h device.h cdrom.h cdrom_image.h cdrom_ioctl.h cdrom_null.h scsi_disk.h win/plat_iodev.h win/resource.h win/win.h + +win_joystick.o: device.h gameport.h win/plat_joystick.h win/resource.h win/win.h + +win_joystickconfig.o: ibm.h config.h device.h gameport.h win/plat_joystick.h win/resource.h win/win.h + +win_keyboard.o: device.h win/plat_keyboard.h win/resource.h win/win.h + +win_language.o: ibm.h device.h ide.h win/plat_ui.h win/resource.h win/win.h win/win_language.h io.h mem.h rom.h device.h ide.h xtide.h + +win_midi.o: ibm.h config.h sound/midi.h win/plat_midi.h win/resource.h + +win_mouse.o: win/plat_mouse.h win/resource.h win/win.h + +win_opendir.o: ibm.h win/plat_dir.h win/resource.h + +win_serial.o: win/plat_thread.h win/plat_serial.h win/resource.h + +win_settings.o: ibm.h mem.h cpu/cpu.h nvr.h device.h model.h cdrom.h disc.h fdd.h hdd.h ide.h scsi.h network/network.h sound/midi.h \ + sound/sound.h sound/snd_dbopl.h sound/snd_mpu401.h video/video.h video/vid_voodoo.h gameport.h mouse.h win/plat_midi.h \ + win/resource.h win/win.h win/win_language.h + +win_status.o: ibm.h mem.h cpu/x86_ops.h cpu/codegen.h device.h win/resource.h win/win.h + +win_video.o: video/video.h win/resource.h win/win_cgapal.h + # End of Makefile.mingw. diff --git a/src/SOUND/midi_fluidsynth.c b/src/SOUND/midi_fluidsynth.c index 4d147aef4..84142b55a 100644 --- a/src/SOUND/midi_fluidsynth.c +++ b/src/SOUND/midi_fluidsynth.c @@ -5,7 +5,9 @@ #include #include #include "../config.h" +#include "../WIN/plat_dynld.h" #include "../WIN/plat_thread.h" +#include "../WIN/plat_ui.h" #include "../device.h" #include "midi_fluidsynth.h" #include "midi.h" @@ -18,6 +20,58 @@ extern void pclog(const char *format, ...); extern void al_set_midi(int freq, int buf_size); extern int soundon; +static void *fluidsynth_handle; /* handle to WinPcap DLL */ + +/* Pointers to the real functions. */ +static fluid_settings_t*(*f_new_fluid_settings)(void); +static void (*f_delete_fluid_settings)(fluid_settings_t *settings); +static int (*f_fluid_settings_setnum)(fluid_settings_t *settings, const char *name, double val); +static int (*f_fluid_settings_getnum)(fluid_settings_t *settings, const char *name, double *val); +static fluid_synth_t * (*f_new_fluid_synth)(fluid_settings_t *settings); +static int (*f_delete_fluid_synth)(fluid_synth_t *synth); +static int (*f_fluid_synth_noteon)(fluid_synth_t *synth, int chan, int key, int vel); +static int (*f_fluid_synth_noteoff)(fluid_synth_t *synth, int chan, int key); +static int (*f_fluid_synth_cc)(fluid_synth_t *synth, int chan, int ctrl, int val); +static int (*f_fluid_synth_sysex)(fluid_synth_t *synth, const char *data, int len, char *response, int *response_len, int *handled, int dryrun); +static int (*f_fluid_synth_pitch_bend)(fluid_synth_t *synth, int chan, int val); +static int (*f_fluid_synth_program_change)(fluid_synth_t *synth, int chan, int program); +static int (*f_fluid_synth_sfload)(fluid_synth_t *synth, const char *filename, int reset_presets); +static int (*f_fluid_synth_sfunload)(fluid_synth_t *synth, unsigned int id, int reset_presets); +static int (*f_fluid_synth_set_interp_method)(fluid_synth_t *synth, int chan, int interp_method); +static void (*f_fluid_synth_set_reverb)(fluid_synth_t *synth, double roomsize, double damping, double width, double level); +static void (*f_fluid_synth_set_reverb_on)(fluid_synth_t *synth, int on); +static void (*f_fluid_synth_set_chorus)(fluid_synth_t *synth, int nr, double level, double speed, double depth_ms, int type); +static void (*f_fluid_synth_set_chorus_on)(fluid_synth_t *synth, int on); +static int (*f_fluid_synth_write_s16)(fluid_synth_t *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr); +static int (*f_fluid_synth_write_float)(fluid_synth_t *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr); +static char* (*f_fluid_version_str)(void); +static dllimp_t fluidsynth_imports[] = { + { "new_fluid_settings", &f_new_fluid_settings }, + { "delete_fluid_settings", &f_delete_fluid_settings }, + { "fluid_settings_setnum", &f_fluid_settings_setnum }, + { "fluid_settings_getnum", &f_fluid_settings_getnum }, + { "new_fluid_synth", &f_new_fluid_synth }, + { "delete_fluid_synth", &f_delete_fluid_synth }, + { "fluid_synth_noteon", &f_fluid_synth_noteon }, + { "fluid_synth_noteoff", &f_fluid_synth_noteoff }, + { "fluid_synth_cc", &f_fluid_synth_cc }, + { "fluid_synth_sysex", &f_fluid_synth_sysex }, + { "fluid_synth_pitch_bend", &f_fluid_synth_pitch_bend }, + { "fluid_synth_program_change", &f_fluid_synth_program_change }, + { "fluid_synth_sfload", &f_fluid_synth_sfload }, + { "fluid_synth_sfunload", &f_fluid_synth_sfload }, + { "fluid_synth_set_interp_method", &f_fluid_synth_set_interp_method }, + { "fluid_synth_set_reverb", &f_fluid_synth_set_reverb }, + { "fluid_synth_set_reverb_on", &f_fluid_synth_set_reverb_on }, + { "fluid_synth_set_chorus", &f_fluid_synth_set_chorus }, + { "fluid_synth_set_chorus_on", &f_fluid_synth_set_chorus_on }, + { "fluid_synth_write_s16", &f_fluid_synth_write_s16 }, + { "fluid_synth_write_float", &f_fluid_synth_write_float }, + { "fluid_version_str", &f_fluid_version_str }, + { NULL, NULL }, +}; + + typedef struct fluidsynth_t { fluid_settings_t* settings; @@ -62,7 +116,7 @@ static void fluidsynth_thread(void *param) { memset(data->buffer, 0, data->buf_size * sizeof(float)); if (data->synth) - fluid_synth_write_float(data->synth, data->buf_size/2, data->buffer, 0, 2, data->buffer, 1, 2); + f_fluid_synth_write_float(data->synth, data->buf_size/2, data->buffer, 0, 2, data->buffer, 1, 2); if (soundon) givealbuffer_midi(data->buffer, data->buf_size); } @@ -70,7 +124,7 @@ static void fluidsynth_thread(void *param) { memset(data->buffer, 0, data->buf_size * sizeof(int16_t)); if (data->synth) - fluid_synth_write_s16(data->synth, data->buf_size/2, data->buffer_int16, 0, 2, data->buffer_int16, 1, 2); + f_fluid_synth_write_s16(data->synth, data->buf_size/2, data->buffer_int16, 0, 2, data->buffer_int16, 1, 2); if (soundon) givealbuffer_midi(data->buffer_int16, data->buf_size); } @@ -90,23 +144,23 @@ void fluidsynth_msg(uint8_t *msg) switch (cmd) { case 0x80: /* Note Off */ - fluid_synth_noteoff(data->synth, chan, param1); + f_fluid_synth_noteoff(data->synth, chan, param1); break; case 0x90: /* Note On */ - fluid_synth_noteon(data->synth, chan, param1, param2); + f_fluid_synth_noteon(data->synth, chan, param1, param2); break; case 0xA0: /* Aftertouch */ break; case 0xB0: /* Control Change */ - fluid_synth_cc(data->synth, chan, param1, param2); + f_fluid_synth_cc(data->synth, chan, param1, param2); break; case 0xC0: /* Program Change */ - fluid_synth_program_change(data->synth, chan, param1); + f_fluid_synth_program_change(data->synth, chan, param1); break; case 0xD0: /* Channel Pressure */ break; case 0xE0: /* Pitch Bend */ - fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1); + f_fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1); break; case 0xF0: /* SysEx */ break; @@ -120,7 +174,7 @@ void fluidsynth_sysex(uint8_t* data, unsigned int len) { fluidsynth_t* d = &fsdev; - fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); + f_fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); } void* fluidsynth_init() @@ -128,19 +182,27 @@ void* fluidsynth_init() fluidsynth_t* data = &fsdev; memset(data, 0, sizeof(fluidsynth_t)); - data->settings = new_fluid_settings(); + /* Try loading the DLL. */ + fluidsynth_handle = dynld_module("libfluidsynth.dll", fluidsynth_imports); + if (fluidsynth_handle == NULL) + { + plat_msgbox_error(IDS_2171); + return NULL; + } - fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); - fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain")/100.0f); + data->settings = f_new_fluid_settings(); - data->synth = new_fluid_synth(data->settings); + f_fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); + f_fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain")/100.0f); + + data->synth = f_new_fluid_synth(data->settings); char* sound_font = device_get_config_string("sound_font"); - data->sound_font = fluid_synth_sfload(data->synth, sound_font, 1); + data->sound_font = f_fluid_synth_sfload(data->synth, sound_font, 1); if (device_get_config_int("chorus")) { - fluid_synth_set_chorus_on(data->synth, 1); + f_fluid_synth_set_chorus_on(data->synth, 1); int chorus_voices = device_get_config_int("chorus_voices"); double chorus_level = device_get_config_int("chorus_level") / 100.0; @@ -153,24 +215,24 @@ void* fluidsynth_init() else chorus_waveform = FLUID_CHORUS_MOD_TRIANGLE; - fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); + f_fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); } else - fluid_synth_set_chorus_on(data->synth, 0); + f_fluid_synth_set_chorus_on(data->synth, 0); if (device_get_config_int("reverb")) { - fluid_synth_set_reverb_on(data->synth, 1); + f_fluid_synth_set_reverb_on(data->synth, 1); double reverb_room_size = device_get_config_int("reverb_room_size") / 100.0; double reverb_damping = device_get_config_int("reverb_damping") / 100.0; int reverb_width = device_get_config_int("reverb_width"); double reverb_level = device_get_config_int("reverb_level") / 100.0; - fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); + f_fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); } else - fluid_synth_set_reverb_on(data->synth, 0); + f_fluid_synth_set_reverb_on(data->synth, 0); int interpolation = device_get_config_int("interpolation"); int fs_interpolation = FLUID_INTERP_4THORDER; @@ -184,10 +246,10 @@ void* fluidsynth_init() else if (interpolation == 3) fs_interpolation = FLUID_INTERP_7THORDER; - fluid_synth_set_interp_method(data->synth, -1, fs_interpolation); + f_fluid_synth_set_interp_method(data->synth, -1, fs_interpolation); double samplerate; - fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); + f_fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); data->samplerate = (int)samplerate; data->buf_size = data->samplerate/RENDER_RATE*2; if (sound_is_float) @@ -205,7 +267,7 @@ void* fluidsynth_init() al_set_midi(data->samplerate, data->buf_size); - pclog("fluidsynth (%s) initialized, samplerate %d, buf_size %d\n", fluid_version_str(), data->samplerate, data->buf_size); + pclog("fluidsynth (%s) initialized, samplerate %d, buf_size %d\n", f_fluid_version_str(), data->samplerate, data->buf_size); midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); @@ -226,9 +288,9 @@ void fluidsynth_close(void* p) fluidsynth_t* data = &fsdev; if (data->sound_font != -1) - fluid_synth_sfunload(data->synth, data->sound_font, 1); - delete_fluid_synth(data->synth); - delete_fluid_settings(data->settings); + f_fluid_synth_sfunload(data->synth, data->sound_font, 1); + f_delete_fluid_synth(data->synth); + f_delete_fluid_settings(data->settings); midi_close(); @@ -242,6 +304,13 @@ void fluidsynth_close(void* p) free(data->buffer_int16); } + /* Unload the DLL if possible. */ + if (fluidsynth_handle != NULL) + { + dynld_close(fluidsynth_handle); + fluidsynth_handle = NULL; + } + pclog("fluidsynth closed\n"); } diff --git a/src/VIDEO/vid_cl_gd_blit.c b/src/VIDEO/vid_cl_gd_blit.c index 18d6642f3..472c1aa84 100644 --- a/src/VIDEO/vid_cl_gd_blit.c +++ b/src/VIDEO/vid_cl_gd_blit.c @@ -652,8 +652,8 @@ void cirrus_bitblt_start(clgd_t *clgd, svga_t *svga) clgd->blt.height = (svga->gdcreg[0x22] | (svga->gdcreg[0x23] << 8)) + 1; clgd->blt.dst_pitch = (svga->gdcreg[0x24] | (svga->gdcreg[0x25] << 8)); clgd->blt.src_pitch = (svga->gdcreg[0x26] | (svga->gdcreg[0x27] << 8)); - clgd->blt.dst_addr = (svga->gdcreg[0x28] | (svga->gdcreg[0x29] << 8) || (svga->gdcreg[0x2a] << 16)); - clgd->blt.src_addr = (svga->gdcreg[0x2c] | (svga->gdcreg[0x2d] << 8) || (svga->gdcreg[0x2e] << 16)); + clgd->blt.dst_addr = (svga->gdcreg[0x28] | (svga->gdcreg[0x29] << 8) | (svga->gdcreg[0x2a] << 16)); + clgd->blt.src_addr = (svga->gdcreg[0x2c] | (svga->gdcreg[0x2d] << 8) | (svga->gdcreg[0x2e] << 16)); clgd->blt.mode = svga->gdcreg[0x30]; clgd->blt.modeext = svga->gdcreg[0x33]; blt_rop = svga->gdcreg[0x32]; diff --git a/src/VIDEO/vid_et4000.c b/src/VIDEO/vid_et4000.c index d20462972..3ea60d376 100644 --- a/src/VIDEO/vid_et4000.c +++ b/src/VIDEO/vid_et4000.c @@ -10,14 +10,14 @@ #include "../device.h" #include "video.h" #include "vid_svga.h" -#include "vid_unk_ramdac.h" +#include "vid_sc1502x_ramdac.h" #include "vid_et4000.h" typedef struct et4000_t { svga_t svga; - unk_ramdac_t ramdac; + sc1502x_ramdac_t ramdac; rom_t bios_rom; @@ -49,7 +49,7 @@ void et4000_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - unk_ramdac_out(addr, val, &et4000->ramdac, svga); + sc1502x_ramdac_out(addr, val, &et4000->ramdac, svga); return; case 0x3CD: /*Banking*/ @@ -96,7 +96,7 @@ uint8_t et4000_in(uint16_t addr, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return unk_ramdac_in(addr, &et4000->ramdac, svga); + return sc1502x_ramdac_in(addr, &et4000->ramdac, svga); case 0x3CD: /*Banking*/ return et4000->banking; diff --git a/src/VIDEO/vid_paradise.c b/src/VIDEO/vid_paradise.c index 939cf506c..799ac8f65 100644 --- a/src/VIDEO/vid_paradise.c +++ b/src/VIDEO/vid_paradise.c @@ -16,7 +16,6 @@ #include "vid_paradise.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_unk_ramdac.h" typedef struct paradise_t diff --git a/src/VIDEO/vid_unk_ramdac.c b/src/VIDEO/vid_sc1502x_ramdac.c similarity index 93% rename from src/VIDEO/vid_unk_ramdac.c rename to src/VIDEO/vid_sc1502x_ramdac.c index c2fb35bae..6e2cc3839 100644 --- a/src/VIDEO/vid_unk_ramdac.c +++ b/src/VIDEO/vid_sc1502x_ramdac.c @@ -9,10 +9,10 @@ #include "../mem.h" #include "video.h" #include "vid_svga.h" -#include "vid_unk_ramdac.h" +#include "vid_sc1502x_ramdac.h" -void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *svga) +void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga) { int oldbpp = 0; switch (addr) @@ -74,7 +74,7 @@ void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *sv svga_out(addr, val, svga); } -uint8_t unk_ramdac_in(uint16_t addr, unk_ramdac_t *ramdac, svga_t *svga) +uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga) { switch (addr) { diff --git a/src/VIDEO/vid_sc1502x_ramdac.h b/src/VIDEO/vid_sc1502x_ramdac.h new file mode 100644 index 000000000..2aaccb391 --- /dev/null +++ b/src/VIDEO/vid_sc1502x_ramdac.h @@ -0,0 +1,11 @@ +/* Copyright holders: Sarah Walker, Tenshi + see COPYING for more details +*/ +typedef struct unk_ramdac_t +{ + int state; + uint8_t ctrl; +} sc1502x_ramdac_t; + +void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga); +uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga); diff --git a/src/VIDEO/vid_unk_ramdac.h b/src/VIDEO/vid_unk_ramdac.h deleted file mode 100644 index ad4c8c1d2..000000000 --- a/src/VIDEO/vid_unk_ramdac.h +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -typedef struct unk_ramdac_t -{ - int state; - uint8_t ctrl; -} unk_ramdac_t; - -void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *svga); -uint8_t unk_ramdac_in(uint16_t addr, unk_ramdac_t *ramdac, svga_t *svga); diff --git a/src/WIN/86Box.rc b/src/WIN/86Box.rc index 776fd8350..bce3ee533 100644 --- a/src/WIN/86Box.rc +++ b/src/WIN/86Box.rc @@ -841,6 +841,7 @@ BEGIN IDS_2168 "&Image..." IDS_2169 "Image (&Write-protected)..." IDS_2170 "Check BPB" + IDS_2171 "Unable to initialize FluidSynth, make sure you have the following libraries\nin your 86Box folder:\n\nlibfluidsynth.dll\nlibglib-2.0-0.dll\nlibiconv-2.dll\nlibintl-8.dll\nlibpcre-1.dll" IDS_3072 "None" IDS_3073 "[Bus] Logitech Bus mouse" diff --git a/src/WIN/plat_ui.h b/src/WIN/plat_ui.h index 120a04e55..92eed6ab6 100644 --- a/src/WIN/plat_ui.h +++ b/src/WIN/plat_ui.h @@ -2,10 +2,6 @@ extern void plat_msgbox_error(int i); extern wchar_t *plat_get_string_from_id(int i); -#ifndef IDS_2219 -#define IDS_2219 2219 -#endif - #ifndef IDS_2077 #define IDS_2077 2077 #endif @@ -21,6 +17,14 @@ extern wchar_t *plat_get_string_from_id(int i); #ifndef IDS_2139 #define IDS_2139 2139 #endif + +#ifndef IDS_2171 +#define IDS_2171 2171 +#endif + +#ifndef IDS_2219 +#define IDS_2219 2219 +#endif #endif extern void plat_msgbox_fatal(char *string); diff --git a/src/WIN/resource.h b/src/WIN/resource.h index 41b933e7f..bd4bf3ea3 100644 --- a/src/WIN/resource.h +++ b/src/WIN/resource.h @@ -321,6 +321,7 @@ #define IDS_2168 2168 // "IDE (PIO-only)" #define IDS_2169 2169 // "%01i:%01i" #define IDS_2170 2170 // "%01i:%01i" +#define IDS_2171 2171 #define IDS_3072 3072 #define IDS_3073 3073 @@ -393,7 +394,7 @@ #define IDS_LANG_ENUS IDS_6144 -#define STRINGS_NUM_2048 123 +#define STRINGS_NUM_2048 124 #define STRINGS_NUM_3072 11 #define STRINGS_NUM_4096 20 #define STRINGS_NUM_4352 7 diff --git a/src/WIN/win_deviceconfig.c b/src/WIN/win_deviceconfig.c index 920595db0..21517727d 100644 --- a/src/WIN/win_deviceconfig.c +++ b/src/WIN/win_deviceconfig.c @@ -41,6 +41,7 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam int cid; device_config_t *config; char s[80]; + wchar_t ws[512]; switch (message) { @@ -423,14 +424,15 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam c++; } strcat(file_filter, "|All files (*.*)|*.*|"); + mbstowcs(ws, file_filter, strlen(file_filter) + 1); d = strlen(file_filter); /* replace | with \0 */ for (c = 0; c < d; ++c) - if (file_filter[c] == '|') - file_filter[c] = '\0'; + if (ws[c] == L'|') + ws[c] = 0; - if (!file_dlg_mb(hdlg, file_filter, s, 0)) + if (!file_dlg(hdlg, ws, s, 0)) SendMessage(h, WM_SETTEXT, 0, (LPARAM)openfilestring); } } @@ -469,8 +471,8 @@ void deviceconfig_open(HWND hwnd, device_t *device) *data++ = 0; /*predefined dialog box class*/ data += MultiByteToWideChar(CP_ACP, 0, "Device Configuration", -1, data, 50); - *data++ = 8; /*Point*/ - data += MultiByteToWideChar(CP_ACP, 0, "MS Sans Serif", -1, data, 50); + *data++ = 9; /*Point*/ + data += MultiByteToWideChar(CP_ACP, 0, "Segoe UI", -1, data, 50); if (((unsigned long)data) & 2) data++; diff --git a/src/WIN/win_settings.c b/src/WIN/win_settings.c index 7b127e17e..d619d3917 100644 --- a/src/WIN/win_settings.c +++ b/src/WIN/win_settings.c @@ -33,7 +33,6 @@ #include "../hdd.h" #include "../ide.h" #include "../scsi.h" -#include "../scsi_buslogic.h" #include "../network/network.h" #include "../sound/midi.h" #include "../sound/sound.h" From 5a343c41110ee16e60b810ed8cab17b8f2054ffd Mon Sep 17 00:00:00 2001 From: waltje Date: Tue, 8 Aug 2017 22:51:47 -0400 Subject: [PATCH 66/82] Made FluidSynth stuff optional (FLUIDSYNTH=n Makefile preamble option.) --- src/Makefile.mingw | 19 +++++++++++-------- src/SOUND/midi.c | 6 +++++- src/SOUND/midi_fluidsynth.c | 5 +++++ src/WIN/86Box.rc | 20 ++++++++++---------- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index f51f57530..8f3007457 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -8,7 +8,7 @@ # # Modified Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.33 2017/08/08 +# Version: @(#)Makefile.mingw 1.0.34 2017/08/09 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -55,6 +55,9 @@ endif ifndef DEV_BRANCH DEV_BRANCH = n endif +ifndef FLUIDSYNTH +FLUIDSYNTH = y +endif ifndef X64 X64 = n endif @@ -124,7 +127,10 @@ ifeq ($(VRAMDUMP), y) CFLAGS += -DENABLE_VRAM_DUMP RFLAGS += -DENABLE_VRAM_DUMP endif - +ifeq ($(FLUIDSYNTH), y) +CFLAGS += -DUSE_FLUIDSYNTH +FSYNTHOBJ = midi_fluidsynth.o +endif ifeq ($(X64), y) PLATCG = codegen_x86-64.o CGOPS = codegen_ops_x86-64.h @@ -177,8 +183,8 @@ SYSOBJ = model.o \ olivetti_m24.o ps1.o ps2.o ps2_mca.o \ tandy_eeprom.o tandy_rom.o DEVOBJ = bugger.o lpt.o $(SERIAL) \ - fdc37c665.o fdc37c669.o fdc37c932fr.o \ - pc87306.o sis85c471.o w83877f.o \ + fdc37c665.o fdc37c669.o fdc37c932fr.o \ + pc87306.o sis85c471.o w83877f.o \ keyboard.o \ keyboard_xt.o keyboard_at.o keyboard_pcjr.o \ keyboard_amstrad.o keyboard_olim24.o \ @@ -213,8 +219,7 @@ SNDOBJ = sound.o \ wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \ wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ wave8580_PST.o wave.o \ - midi.o \ - midi_fluidsynth.o \ + midi.o $(FSYNTHOBJ) \ midi_mt32.o \ Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ LA32FloatWaveGenerator.o LA32WaveGenerator.o \ @@ -325,8 +330,6 @@ pcap_if.res: pcap_if.rc # Module dependencies. - -# / acer386sx.o: ibm.h cpu/cpu.h io.h device.h model.h ali1429.o: ibm.h cpu/cpu.h io.h mem.h device.h model.h diff --git a/src/SOUND/midi.c b/src/SOUND/midi.c index 9a80e30f2..7fb844f7f 100644 --- a/src/SOUND/midi.c +++ b/src/SOUND/midi.c @@ -8,7 +8,9 @@ #include "../WIN/plat_midi.h" #include "../WIN/plat_ticks.h" -#include "midi_fluidsynth.h" +#ifdef USE_FLUIDSYNTH +# include "midi_fluidsynth.h" +#endif #include "midi_mt32.h" #include "midi_system.h" @@ -25,7 +27,9 @@ typedef struct static MIDI_DEVICE devices[] = { {"None", "none", NULL}, +#ifdef USE_FLUIDSYNTH {"FluidSynth", "fluidsynth", &fluidsynth_device}, +#endif {"Roland MT-32 Emulation", "mt32", &mt32_device}, {"Roland CM-32L Emulation", "cm32l", &cm32l_device}, {SYSTEM_MIDI_NAME, SYSTEM_MIDI_INTERNAL_NAME, &system_midi_device}, diff --git a/src/SOUND/midi_fluidsynth.c b/src/SOUND/midi_fluidsynth.c index 84142b55a..307bc0f91 100644 --- a/src/SOUND/midi_fluidsynth.c +++ b/src/SOUND/midi_fluidsynth.c @@ -1,4 +1,6 @@ /* some code borrowed from scummvm */ +#ifdef USE_FLUIDSYNTH + #include #include @@ -502,3 +504,6 @@ device_t fluidsynth_device = NULL, fluidsynth_config }; + + +#endif /*USE_FLUIDSYNTH*/ diff --git a/src/WIN/86Box.rc b/src/WIN/86Box.rc index bce3ee533..dedc5be47 100644 --- a/src/WIN/86Box.rc +++ b/src/WIN/86Box.rc @@ -8,7 +8,7 @@ * * Windows resource script. * - * Version: @(#)86Box.rc 1.0.4 2017/06/17 + * Version: @(#)86Box.rc 1.0.5 2017/08/08 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -844,16 +844,16 @@ BEGIN IDS_2171 "Unable to initialize FluidSynth, make sure you have the following libraries\nin your 86Box folder:\n\nlibfluidsynth.dll\nlibglib-2.0-0.dll\nlibiconv-2.dll\nlibintl-8.dll\nlibpcre-1.dll" IDS_3072 "None" - IDS_3073 "[Bus] Logitech Bus mouse" - IDS_3074 "[Bus] InPort mouse" - IDS_3075 "[Serial] Mouse Systems mouse" - IDS_3076 "[Serial] Microsoft 2-button mouse" - IDS_3077 "[Serial] Logitech 3-button mouse" - IDS_3078 "[Serial] Microsoft wheel mouse" - IDS_3079 "[PS/2] 2-button mouse" + IDS_3073 "[Bus] Logitech Bus Mouse" + IDS_3074 "[Bus] Microsoft Bus Mouse (InPort)" + IDS_3075 "[Serial] Mouse Systems Mouse" + IDS_3076 "[Serial] Microsoft 2-button Mouse" + IDS_3077 "[Serial] Logitech 3-button Mouse" + IDS_3078 "[Serial] Microsoft Wheel Mouse" + IDS_3079 "[PS/2] 2-button Mouse" IDS_3080 "[PS/2] Microsoft Intellimouse" - IDS_3081 "[Proprietary] Amstrad mouse" - IDS_3082 "[Proprietary] Olivetti M24 mouse" + IDS_3081 "[Proprietary] Amstrad Mouse" + IDS_3082 "[Proprietary] Olivetti M24 Mouse" IDS_4096 "Hard disk (%s)" IDS_4097 "%01i:%01i" From aad11eac50d83c04a1e11e59f7b52832130edb34 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Aug 2017 15:43:35 +0200 Subject: [PATCH 67/82] Fixed a FluidSynth import bug, soundfonts should now be loaded correctly again. --- src/SOUND/midi_fluidsynth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SOUND/midi_fluidsynth.c b/src/SOUND/midi_fluidsynth.c index 307bc0f91..7fdea0bb4 100644 --- a/src/SOUND/midi_fluidsynth.c +++ b/src/SOUND/midi_fluidsynth.c @@ -61,7 +61,7 @@ static dllimp_t fluidsynth_imports[] = { { "fluid_synth_pitch_bend", &f_fluid_synth_pitch_bend }, { "fluid_synth_program_change", &f_fluid_synth_program_change }, { "fluid_synth_sfload", &f_fluid_synth_sfload }, - { "fluid_synth_sfunload", &f_fluid_synth_sfload }, + { "fluid_synth_sfunload", &f_fluid_synth_sfunload }, { "fluid_synth_set_interp_method", &f_fluid_synth_set_interp_method }, { "fluid_synth_set_reverb", &f_fluid_synth_set_reverb }, { "fluid_synth_set_reverb_on", &f_fluid_synth_set_reverb_on }, From c77e04461a81cb71674ea919cd83562654bd9938 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Aug 2017 20:03:15 +0200 Subject: [PATCH 68/82] The SCSI controller now use TIMER_USEC based time. --- src/scsi_aha154x.c | 8 ++++---- src/scsi_buslogic.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index 3259c5e58..9c9c37cee 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -1375,7 +1375,7 @@ aha_write(uint16_t port, uint8_t val, void *priv) /* If there are no mailboxes configured, don't even try to do anything. */ if (dev->MailboxCount) { if (!AHA_Callback) { - AHA_Callback = SCSI_DELAY_TM * SCSI_TIME; + AHA_Callback = 1 * TIMER_USEC; } } return; @@ -2110,7 +2110,7 @@ aha_cmd_cb(void *priv) if (dev->MailboxCount) { aha_do_mail(dev); } else { - AHA_Callback += SCSI_DELAY_TM * SCSI_TIME; + AHA_Callback += 1 * TIMER_USEC; return; } } else if (AHA_InOperation == 1) { @@ -2119,7 +2119,7 @@ aha_cmd_cb(void *priv) if (dev->Req.CmdBlock.common.Cdb[0] == 0x42) { /* This is needed since CD Audio inevitably means READ SUBCHANNEL spam. */ - AHA_Callback += 1000 * SCSI_TIME; + AHA_Callback += 1000 * TIMER_USEC; return; } } else if (AHA_InOperation == 2) { @@ -2132,7 +2132,7 @@ aha_cmd_cb(void *priv) fatal("Invalid BusLogic callback phase: %i\n", AHA_InOperation); } - AHA_Callback += SCSI_DELAY_TM * SCSI_TIME; + AHA_Callback += 1 * TIMER_USEC; } uint8_t aha_mca_read(int port, void *p) diff --git a/src/scsi_buslogic.c b/src/scsi_buslogic.c index 2da990ee4..94348fe76 100644 --- a/src/scsi_buslogic.c +++ b/src/scsi_buslogic.c @@ -1080,7 +1080,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) /* If there are no mailboxes configured, don't even try to do anything. */ if (bl->MailboxCount) { if (!BuslogicCallback) { - BuslogicCallback = 50 * SCSI_TIME; + BuslogicCallback = 1 * TIMER_USEC; } } return; @@ -1996,7 +1996,7 @@ BuslogicCommandCallback(void *p) if (bl->MailboxCount) { BuslogicProcessMailbox(bl); } else { - BuslogicCallback += 50 * SCSI_TIME; + BuslogicCallback += 1 * TIMER_USEC; return; } } else if (BuslogicInOperation == 1) { @@ -2005,7 +2005,7 @@ BuslogicCommandCallback(void *p) if (bl->Req.CmdBlock.common.Cdb[0] == 0x42) { /* This is needed since CD Audio inevitably means READ SUBCHANNEL spam. */ - BuslogicCallback += 1000 * SCSI_TIME; + BuslogicCallback += 1000 * TIMER_USEC; return; } } else if (BuslogicInOperation == 2) { @@ -2018,7 +2018,7 @@ BuslogicCommandCallback(void *p) fatal("Invalid BusLogic callback phase: %i\n", BuslogicInOperation); } - BuslogicCallback += 50 * SCSI_TIME; + BuslogicCallback += 1 * TIMER_USEC; } From 9e09080abf265f65794bafca996c3818990bb04e Mon Sep 17 00:00:00 2001 From: waltje Date: Wed, 9 Aug 2017 14:22:21 -0400 Subject: [PATCH 69/82] Fixed typo and other minor changes. --- src/SOUND/midi_fluidsynth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SOUND/midi_fluidsynth.c b/src/SOUND/midi_fluidsynth.c index 7fdea0bb4..453997065 100644 --- a/src/SOUND/midi_fluidsynth.c +++ b/src/SOUND/midi_fluidsynth.c @@ -22,7 +22,7 @@ extern void pclog(const char *format, ...); extern void al_set_midi(int freq, int buf_size); extern int soundon; -static void *fluidsynth_handle; /* handle to WinPcap DLL */ +static void *fluidsynth_handle; /* handle to FluidSynth DLL */ /* Pointers to the real functions. */ static fluid_settings_t*(*f_new_fluid_settings)(void); @@ -74,7 +74,7 @@ static dllimp_t fluidsynth_imports[] = { }; -typedef struct fluidsynth_t +typedef struct fluidsynth { fluid_settings_t* settings; fluid_synth_t* synth; @@ -92,12 +92,12 @@ typedef struct fluidsynth_t fluidsynth_t fsdev; -int fluidsynth_available() +int fluidsynth_available(void) { return 1; } -void fluidsynth_poll() +void fluidsynth_poll(void) { fluidsynth_t* data = &fsdev; data->midi_pos++; @@ -179,7 +179,7 @@ void fluidsynth_sysex(uint8_t* data, unsigned int len) f_fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); } -void* fluidsynth_init() +void* fluidsynth_init(void) { fluidsynth_t* data = &fsdev; memset(data, 0, sizeof(fluidsynth_t)); From a398845ad073ecde1f4ce4cf91ad86b46c5a66f5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 10 Aug 2017 16:15:53 +0200 Subject: [PATCH 70/82] The AHA-1540B now uses the correct BIOS. --- src/scsi_aha154x.c | 182 +++++++++++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 63 deletions(-) diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index 9c9c37cee..1111f86a3 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -287,9 +287,16 @@ aha_patch(uint8_t *romptr, uint16_t ioaddr) #endif +enum { + CHIP_AHA154XB, + CHIP_AHA154XCF, + CHIP_AHA1640 +}; + + /* Initialize AHA-154xNN-specific stuff. */ static void -aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha, int irq, int dma) +aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha, int irq, int dma, int chip) { uint32_t bios_size; uint32_t bios_addr; @@ -300,7 +307,15 @@ aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha, int irq, int dma) /* Set BIOS load address. */ bios_addr = memaddr; - bios_path = ROMFILE; + /* bios_path = ROMFILE; */ + if (chip == CHIP_AHA154XB) + { + bios_path = L"roms/scsi/adaptec/aha1540b310.bin"; + } + else + { + bios_path = L"roms/scsi/adaptec/aha1542cf201.bin"; + } pclog_w(L"AHA154x: loading BIOS from '%s'\n", bios_path); /* Open the BIOS image file and make sure it exists. */ @@ -371,6 +386,7 @@ aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha, int irq, int dma) aha_mem_write, NULL, NULL, aha_bios.rom, MEM_MAPPING_EXTERNAL, &aha_bios); +#if 0 #ifdef ROM_IOADDR /* Patch the ROM BIOS image to work with us. */ aha_patch(aha_bios.rom, ioaddr); @@ -385,7 +401,26 @@ aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha, int irq, int dma) aha->fwh = '1'; aha->fwl = '0'; #endif - aha->bid = AHA_BID; +#endif + + if (chip == CHIP_AHA154XB) + { + /* Fake BIOS firmware version. */ + aha->fwh = '1'; + aha->fwl = '0'; + } + else + { + /* Patch the ROM BIOS image to work with us. */ + aha_patch(aha_bios.rom, ioaddr); + + /* Read firmware version from the BIOS. */ + aha->fwh = aha_bios.rom[ROM_FWHIGH]; + aha->fwl = aha_bios.rom[ROM_FWHIGH+1]; + } + + /* aha->bid = AHA_BID; */ + aha->bid = (chip == CHIP_AHA154XB) ? 'A' : 'E'; /* * Do a checksum on the ROM. @@ -415,42 +450,47 @@ again: mem_mapping_enable(&aha_bios.mapping); mem_mapping_set_addr(&aha_bios.mapping, bios_addr, bios_size); -#ifdef EEP_SIZE +/* #ifdef EEP_SIZE */ /* Initialize the on-board EEPROM. */ - memset(aha_eep, 0x00, EEP_SIZE); - aha_eep[0] = 7; /* SCSI ID 7 */ - aha_eep[0] |= (0x10 | 0x20 | 0x40); - aha_eep[1] = irq-9; /* IRQ15 */ - aha_eep[1] |= (dma<<4); /* DMA6 */ - aha_eep[2] = (EE2_HABIOS | /* BIOS enabled */ - EE2_DYNSCAN | /* scan bus */ - EE2_EXT1G | EE2_RMVOK);/* Immediate return on seek */ - aha_eep[3] = SPEED_50; /* speed 5.0 MB/s */ - aha_eep[6] = (EE6_TERM | /* host term enable */ - EE6_RSTBUS); /* reset SCSI bus on boot */ -#endif + if (chip != CHIP_AHA154XB) + { + memset(aha_eep, 0x00, EEP_SIZE); + aha_eep[0] = 7; /* SCSI ID 7 */ + aha_eep[0] |= (0x10 | 0x20 | 0x40); + aha_eep[1] = irq-9; /* IRQ15 */ + aha_eep[1] |= (dma<<4); /* DMA6 */ + aha_eep[2] = (EE2_HABIOS | /* BIOS enabled */ + EE2_DYNSCAN | /* scan bus */ + EE2_EXT1G | EE2_RMVOK);/* Immediate return on seek */ + aha_eep[3] = SPEED_50; /* speed 5.0 MB/s */ + aha_eep[6] = (EE6_TERM | /* host term enable */ + EE6_RSTBUS); /* reset SCSI bus on boot */ + } +/* #endif */ } /* Mess with the AHA-154xCF's Shadow RAM. */ static uint8_t -aha154x_shram(uint8_t cmd) +aha154x_shram(uint8_t cmd, int chip) { -#ifdef ROM_SHRAM - switch(cmd) { - case 0x00: /* disable, make it look like ROM */ - memset(&aha_bios.rom[ROM_SHRAM], 0xFF, ROM_SHRAMSZ); - break; +/* #ifdef ROM_SHRAM */ + if (chip != CHIP_AHA154XB) { + switch(cmd) { + case 0x00: /* disable, make it look like ROM */ + memset(&aha_bios.rom[ROM_SHRAM], 0xFF, ROM_SHRAMSZ); + break; - case 0x02: /* clear it */ - memset(&aha_bios.rom[ROM_SHRAM], 0x00, ROM_SHRAMSZ); - break; + case 0x02: /* clear it */ + memset(&aha_bios.rom[ROM_SHRAM], 0x00, ROM_SHRAMSZ); + break; - case 0x03: /* enable, clear for use */ - memset(&aha_bios.rom[ROM_SHRAM], 0x00, ROM_SHRAMSZ); + case 0x03: /* enable, clear for use */ + memset(&aha_bios.rom[ROM_SHRAM], 0x00, ROM_SHRAMSZ); break; + } } -#endif +/* #endif */ /* Firmware expects 04 status. */ return(0x04); @@ -458,28 +498,30 @@ aha154x_shram(uint8_t cmd) static uint8_t -aha154x_eeprom(uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp) +aha154x_eeprom(uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp, int chip) { uint8_t r = 0xff; pclog("AHA154x: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n", cmd, arg, len, off); -#ifdef EEP_SIZE - if ((off+len) > EEP_SIZE) return(r); /* no can do.. */ +/* #ifdef EEP_SIZE */ + if (chip != CHIP_AHA154XB) { + if ((off+len) > EEP_SIZE) return(r); /* no can do.. */ - if (cmd == 0x22) { - /* Write data to the EEPROM. */ - memcpy(&aha_eep[off], bufp, len); - r = 0; - } + if (cmd == 0x22) { + /* Write data to the EEPROM. */ + memcpy(&aha_eep[off], bufp, len); + r = 0; + } - if (cmd == 0x23) { - /* Read data from the EEPROM. */ - memcpy(bufp, &aha_eep[off], len); - r = len; + if (cmd == 0x23) { + /* Read data from the EEPROM. */ + memcpy(bufp, &aha_eep[off], len); + r = len; + } } -#endif +/* #endif */ return(r); } @@ -862,13 +904,6 @@ static int AHA_InOperation = 0; static aha_t *ResetDev; -enum { - CHIP_AHA154XB, - CHIP_AHA154XCF, - CHIP_AHA1640 -}; - - static void ClearIntr(aha_t *dev) { @@ -1431,7 +1466,10 @@ aha_write(uint16_t port, uint8_t val, void *priv) break; case 0x29: - dev->CmdParamLeft = 2; + if (dev->chip != CHIP_AHA154XB) + { + dev->CmdParamLeft = 2; + } break; case 0x91: @@ -1602,7 +1640,8 @@ aha_0x01: dev->CmdBuf[0], dev->CmdBuf[1], dev->CmdBuf[2], - &dev->CmdBuf[3]); + dev->DataBuf, + dev->chip); if (dev->DataReplyLeft == 0xff) { dev->DataReplyLeft = 0; dev->Status |= STAT_INVCMD; @@ -1615,7 +1654,8 @@ aha_0x01: dev->CmdBuf[0], dev->CmdBuf[1], dev->CmdBuf[2], - dev->DataBuf); + dev->DataBuf, + dev->chip); if (dev->DataReplyLeft == 0xff) { dev->DataReplyLeft = 0; dev->Status |= STAT_INVCMD; @@ -1630,7 +1670,7 @@ aha_0x01: * and expects a 0x04 back in the INTR * register. --FvK */ - dev->Interrupt = aha154x_shram(val); + dev->Interrupt = aha154x_shram(val, dev->chip); break; case 0x25: @@ -1643,20 +1683,34 @@ aha_0x01: break; case 0x28: - dev->DataBuf[0] = 0x08; - dev->DataBuf[1] = dev->Lock; - dev->DataReplyLeft = 2; + if (dev->chip == CHIP_AHA154XB) + { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + else + { + dev->DataBuf[0] = 0x08; + dev->DataBuf[1] = dev->Lock; + dev->DataReplyLeft = 2; + } break; - case 0x29: - if (dev->CmdBuf[1] == dev->Lock) { - if (dev->CmdBuf[0] & 1) { - dev->Lock = 1; - } else { - dev->Lock = 0; + dev->DataReplyLeft = 0; + if (dev->chip == CHIP_AHA154XB) + { + dev->Status |= STAT_INVCMD; + } + else + { + if (dev->CmdBuf[1] == dev->Lock) { + if (dev->CmdBuf[0] & 1) { + dev->Lock = 1; + } else { + dev->Lock = 0; + } } } - dev->DataReplyLeft = 0; break; case 0x2C: /* AHA-1542CP sends this */ @@ -2116,6 +2170,7 @@ aha_cmd_cb(void *priv) } else if (AHA_InOperation == 1) { pclog("BusLogic Callback: Process CD-ROM request\n"); aha_cdrom_cmd(dev); + aha_mbi(dev); if (dev->Req.CmdBlock.common.Cdb[0] == 0x42) { /* This is needed since CD Audio inevitably means READ SUBCHANNEL spam. */ @@ -2128,6 +2183,7 @@ aha_cmd_cb(void *priv) } else if (AHA_InOperation == 0x11) { pclog("BusLogic Callback: Process DISK request\n"); aha_disk_cmd(dev); + aha_mbi(dev); } else { fatal("Invalid BusLogic callback phase: %i\n", AHA_InOperation); } @@ -2260,7 +2316,7 @@ aha_init(int chip, int has_bios) if (bios) { /* Perform AHA-154xNN-specific initialization. */ - aha154x_bios(dev->Base, bios_addr, &dev->aha, dev->Irq, dev->DmaChannel); + aha154x_bios(dev->Base, bios_addr, &dev->aha, dev->Irq, dev->DmaChannel, chip); } return(dev); From 4c40b234125af642cbd0e420380001f497f35b98 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 10 Aug 2017 23:46:06 +0200 Subject: [PATCH 71/82] Updated MUNT to 2.2.0. --- src/Makefile.mingw | 6 +- src/SOUND/midi_mt32.c | 65 +++--------- src/SOUND/munt/Analog.h | 2 +- src/SOUND/munt/BReverbModel.h | 2 +- src/SOUND/munt/Enumerations.h | 1 - src/SOUND/munt/LA32FloatWaveGenerator.cpp | 15 ++- src/SOUND/munt/LA32Ramp.cpp | 15 ++- src/SOUND/munt/LA32Ramp.h | 1 + src/SOUND/munt/LA32WaveGenerator.cpp | 31 +++--- src/SOUND/munt/MidiStreamParser.cpp | 2 +- src/SOUND/munt/Part.cpp | 15 ++- src/SOUND/munt/Partial.cpp | 8 +- src/SOUND/munt/Partial.h | 1 + src/SOUND/munt/ROMInfo.cpp | 2 + src/SOUND/munt/SampleRateConverter_dummy.cpp | 60 +++++++++++ src/SOUND/munt/Structures.h | 6 ++ src/SOUND/munt/Synth.cpp | 99 ++++++++++++++++--- src/SOUND/munt/Synth.h | 24 ++++- src/SOUND/munt/TVA.cpp | 29 ++++-- src/SOUND/munt/TVF.cpp | 17 +++- src/SOUND/munt/TVP.cpp | 82 +++++++++------ src/SOUND/munt/TVP.h | 1 - src/SOUND/munt/c_interface/c_interface.cpp | 96 ++++++++++++++++-- src/SOUND/munt/c_interface/c_interface.h | 20 +++- src/SOUND/munt/c_interface/c_types.h | 16 ++- src/SOUND/munt/c_interface/cpp_interface.h | 11 +++ src/SOUND/munt/config.h | 4 +- src/SOUND/munt/globals.h | 2 +- .../srctools/include/FloatSampleProvider.h | 2 +- .../srctools/include/ResamplerStage.h | 2 +- 30 files changed, 471 insertions(+), 166 deletions(-) create mode 100644 src/SOUND/munt/SampleRateConverter_dummy.cpp diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 8f3007457..5adf466e6 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -8,7 +8,7 @@ # # Modified Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.34 2017/08/09 +# Version: @(#)Makefile.mingw 1.0.35 2017/08/10 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -224,8 +224,8 @@ SNDOBJ = sound.o \ Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ LA32FloatWaveGenerator.o LA32WaveGenerator.o \ MidiStreamParser.o Part.o Partial.o PartialManager.o \ - Poly.o ROMInfo.o Synth.o Tables.o TVA.o TVF.o TVP.o \ - sha1.o c_interface.o \ + Poly.o ROMInfo.o SampleRateConverter_dummy.o Synth.o \ + Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o \ midi_system.o \ snd_speaker.o snd_ps1.o snd_pssj.o \ snd_adlib.o snd_adlibgold.o snd_ad1848.o \ diff --git a/src/SOUND/midi_mt32.c b/src/SOUND/midi_mt32.c index dbcc46a50..ddf561ee0 100644 --- a/src/SOUND/midi_mt32.c +++ b/src/SOUND/midi_mt32.c @@ -178,6 +178,7 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) mt32emu_set_reverb_enabled(context, device_get_config_int("reverb")); mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain")/100.0f); mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo")); + mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp")); pclog("mt32 output gain: %f\n", mt32emu_get_output_gain(context)); pclog("mt32 reverb output gain: %f\n", mt32emu_get_reverb_output_gain(context)); @@ -248,32 +249,11 @@ static device_config_t mt32_config[] = { .name = "output_gain", .description = "Output Gain", - .type = CONFIG_SELECTION, - .selection = + .type = CONFIG_SPINNER, + .spinner = { - { - .description = "100%", - .value = 100 - }, - { - .description = "75%", - .value = 75 - }, - { - .description = "50%", - .value = 50 - }, - { - .description = "25%", - .value = 25 - }, - { - .description = "0%", - .value = 0 - }, - { - .description = "" - } + .min = 0, + .max = 100 }, .default_int = 100 }, @@ -286,32 +266,11 @@ static device_config_t mt32_config[] = { .name = "reverb_output_gain", .description = "Reverb Output Gain", - .type = CONFIG_SELECTION, - .selection = + .type = CONFIG_SPINNER, + .spinner = { - { - .description = "100%", - .value = 100 - }, - { - .description = "75%", - .value = 75 - }, - { - .description = "50%", - .value = 50 - }, - { - .description = "25%", - .value = 25 - }, - { - .description = "0%", - .value = 0 - }, - { - .description = "" - } + .min = 0, + .max = 100 }, .default_int = 100 }, @@ -321,6 +280,12 @@ static device_config_t mt32_config[] = .type = CONFIG_BINARY, .default_int = 0 }, + { + .name = "nice_ramp", + .description = "Nice ramp", + .type = CONFIG_BINARY, + .default_int = 1 + }, { .type = -1 } diff --git a/src/SOUND/munt/Analog.h b/src/SOUND/munt/Analog.h index edaab4fe2..3b6dcabfa 100644 --- a/src/SOUND/munt/Analog.h +++ b/src/SOUND/munt/Analog.h @@ -38,7 +38,7 @@ class Analog { public: static Analog *createAnalog(const AnalogOutputMode mode, const bool oldMT32AnalogLPF, const RendererType rendererType); - virtual ~Analog() {}; + virtual ~Analog() {} virtual unsigned int getOutputSampleRate() const = 0; virtual Bit32u getDACStreamsLength(const Bit32u outputLength) const = 0; virtual void setSynthOutputGain(const float synthGain) = 0; diff --git a/src/SOUND/munt/BReverbModel.h b/src/SOUND/munt/BReverbModel.h index 2d0c5b5ff..5b1d41198 100644 --- a/src/SOUND/munt/BReverbModel.h +++ b/src/SOUND/munt/BReverbModel.h @@ -29,7 +29,7 @@ class BReverbModel { public: static BReverbModel *createBReverbModel(const ReverbMode mode, const bool mt32CompatibleModel, const RendererType rendererType); - virtual ~BReverbModel() {}; + virtual ~BReverbModel() {} virtual bool isOpen() const = 0; // After construction or a close(), open() must be called at least once before any other call (with the exception of close()). virtual void open() = 0; diff --git a/src/SOUND/munt/Enumerations.h b/src/SOUND/munt/Enumerations.h index 8dad8e88e..bb580ca5b 100644 --- a/src/SOUND/munt/Enumerations.h +++ b/src/SOUND/munt/Enumerations.h @@ -85,7 +85,6 @@ enum MT32EMU_DAC_INPUT_MODE_NAME { * Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) * Much less likely to overdrive than any other mode. * Half the volume of any of the other modes. - * Output gain is ignored for both LA32 and reverb output. * Perfect for developers while debugging :) */ MT32EMU_DAC_INPUT_MODE(PURE), diff --git a/src/SOUND/munt/LA32FloatWaveGenerator.cpp b/src/SOUND/munt/LA32FloatWaveGenerator.cpp index 5cc04fdeb..6ff4aa37b 100644 --- a/src/SOUND/munt/LA32FloatWaveGenerator.cpp +++ b/src/SOUND/munt/LA32FloatWaveGenerator.cpp @@ -165,12 +165,6 @@ float LA32FloatWaveGenerator::generateNextSample(const Bit32u ampVal, const Bit1 hLen = 0.0f; } - // Ignore pulsewidths too high for given freq and cutoff - float lLen = waveLen - hLen - 2 * cosineLen; - if (lLen < 0.0f) { - lLen = 0.0f; - } - // Correct resAmp for cutoff in range 50..66 if ((cutoffVal >= MIDDLE_CUTOFF_VALUE) && (cutoffVal < RESONANCE_DECAY_THRESHOLD_CUTOFF_VALUE)) { resAmp *= sin(FLOAT_PI * (cutoffVal - MIDDLE_CUTOFF_VALUE) / 32.0f); @@ -328,8 +322,13 @@ static inline float produceDistortedSample(float sample) { } float LA32FloatPartialPair::nextOutSample() { + // Note, LA32FloatWaveGenerator produces each sample normalised in terms of a single playing partial, + // so the unity sample corresponds to the internal LA32 logarithmic fixed-point unity sample. + // However, each logarithmic sample is then unlogged to a 14-bit signed integer value, i.e. the max absolute value is 8192. + // Thus, considering that samples are further mapped to a 16-bit signed integer, + // we apply a conversion factor 0.25 to produce properly normalised float samples. if (!ringModulated) { - return masterOutputSample + slaveOutputSample; + return 0.25f * (masterOutputSample + slaveOutputSample); } /* * SEMI-CONFIRMED: Ring modulation model derived from sample analysis of specially constructed patches which exploit distortion. @@ -340,7 +339,7 @@ float LA32FloatPartialPair::nextOutSample() { * Most probably the overflow is caused by limited precision of the multiplication circuit as the very similar distortion occurs with panning. */ float ringModulatedSample = produceDistortedSample(masterOutputSample) * produceDistortedSample(slaveOutputSample); - return mixed ? masterOutputSample + ringModulatedSample : ringModulatedSample; + return 0.25f * (mixed ? masterOutputSample + ringModulatedSample : ringModulatedSample); } void LA32FloatPartialPair::deactivate(const PairType useMaster) { diff --git a/src/SOUND/munt/LA32Ramp.cpp b/src/SOUND/munt/LA32Ramp.cpp index fda38d440..9dcf143fb 100644 --- a/src/SOUND/munt/LA32Ramp.cpp +++ b/src/SOUND/munt/LA32Ramp.cpp @@ -56,8 +56,8 @@ We haven't fully explored: namespace MT32Emu { // SEMI-CONFIRMED from sample analysis. -const int TARGET_MULT = 0x40000; -const unsigned int MAX_CURRENT = 0xFF * TARGET_MULT; +const unsigned int TARGET_SHIFTS = 18; +const unsigned int MAX_CURRENT = 0xFF << TARGET_SHIFTS; // We simulate the delay in handling "target was reached" interrupts by waiting // this many samples before setting interruptRaised. @@ -96,7 +96,7 @@ void LA32Ramp::startRamp(Bit8u target, Bit8u increment) { largeIncrement++; } - largeTarget = target * TARGET_MULT; + largeTarget = target << TARGET_SHIFTS; interruptCountdown = 0; interruptRaised = false; } @@ -152,4 +152,13 @@ void LA32Ramp::reset() { interruptRaised = false; } +// This is actually beyond the LA32 ramp interface. +// Instead of polling the current value, MCU receives an interrupt when a ramp completes. +// However, this is a simple way to work around the specific behaviour of TVA +// when in sustain phase which one normally wants to avoid. +// See TVA::recalcSustain() for details. +bool LA32Ramp::isBelowCurrent(Bit8u target) const { + return Bit32u(target << TARGET_SHIFTS) < current; +} + } // namespace MT32Emu diff --git a/src/SOUND/munt/LA32Ramp.h b/src/SOUND/munt/LA32Ramp.h index 25e70c22a..959a1ad37 100644 --- a/src/SOUND/munt/LA32Ramp.h +++ b/src/SOUND/munt/LA32Ramp.h @@ -39,6 +39,7 @@ public: Bit32u nextValue(); bool checkInterrupt(); void reset(); + bool isBelowCurrent(Bit8u target) const; }; } // namespace MT32Emu diff --git a/src/SOUND/munt/LA32WaveGenerator.cpp b/src/SOUND/munt/LA32WaveGenerator.cpp index 9bdf40610..f6f692880 100644 --- a/src/SOUND/munt/LA32WaveGenerator.cpp +++ b/src/SOUND/munt/LA32WaveGenerator.cpp @@ -378,22 +378,16 @@ Bit16s LA32IntPartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg) { return firstSample + secondSample; } +static inline Bit16s produceDistortedSample(Bit16s sample) { + return ((sample & 0x2000) == 0) ? Bit16s(sample & 0x1fff) : Bit16s(sample | ~0x1fff); +} + Bit16s LA32IntPartialPair::nextOutSample() { if (!ringModulated) { return unlogAndMixWGOutput(master) + unlogAndMixWGOutput(slave); } - /* - * SEMI-CONFIRMED: Ring modulation model derived from sample analysis of specially constructed patches which exploit distortion. - * LA32 ring modulator found to produce distorted output in case if the absolute value of maximal amplitude of one of the input partials exceeds 8191. - * This is easy to reproduce using synth partials with resonance values close to the maximum. It looks like an integer overflow happens in this case. - * As the distortion is strictly bound to the amplitude of the complete mixed square + resonance wave in the linear space, - * it is reasonable to assume the ring modulation is performed also in the linear space by sample multiplication. - * Most probably the overflow is caused by limited precision of the multiplication circuit as the very similar distortion occurs with panning. - */ - Bit16s nonOverdrivenMasterSample = unlogAndMixWGOutput(master); // Store master partial sample for further mixing - Bit16s masterSample = nonOverdrivenMasterSample << 2; - masterSample >>= 2; + Bit16s masterSample = unlogAndMixWGOutput(master); // Store master partial sample for further mixing /* SEMI-CONFIRMED from sample analysis: * We observe that for partial structures with ring modulation the interpolation is not applied to the slave PCM partial. @@ -401,10 +395,17 @@ Bit16s LA32IntPartialPair::nextOutSample() { * is borrowed by the ring modulation circuit (or the LA32 chip has a similar lack of resources assigned to each partial pair). */ Bit16s slaveSample = slave.isPCMWave() ? LA32Utilites::unlog(slave.getOutputLogSample(true)) : unlogAndMixWGOutput(slave); - slaveSample <<= 2; - slaveSample >>= 2; - Bit16s ringModulatedSample = Bit16s((Bit32s(masterSample) * Bit32s(slaveSample)) >> 13); - return mixed ? nonOverdrivenMasterSample + ringModulatedSample : ringModulatedSample; + + /* SEMI-CONFIRMED: Ring modulation model derived from sample analysis of specially constructed patches which exploit distortion. + * LA32 ring modulator found to produce distorted output in case if the absolute value of maximal amplitude of one of the input partials exceeds 8191. + * This is easy to reproduce using synth partials with resonance values close to the maximum. It looks like an integer overflow happens in this case. + * As the distortion is strictly bound to the amplitude of the complete mixed square + resonance wave in the linear space, + * it is reasonable to assume the ring modulation is performed also in the linear space by sample multiplication. + * Most probably the overflow is caused by limited precision of the multiplication circuit as the very similar distortion occurs with panning. + */ + Bit16s ringModulatedSample = Bit16s((Bit32s(produceDistortedSample(masterSample)) * Bit32s(produceDistortedSample(slaveSample))) >> 13); + + return mixed ? masterSample + ringModulatedSample : ringModulatedSample; } void LA32IntPartialPair::deactivate(const PairType useMaster) { diff --git a/src/SOUND/munt/MidiStreamParser.cpp b/src/SOUND/munt/MidiStreamParser.cpp index 3a70bec18..a426a20cc 100644 --- a/src/SOUND/munt/MidiStreamParser.cpp +++ b/src/SOUND/munt/MidiStreamParser.cpp @@ -119,7 +119,7 @@ void MidiStreamParserImpl::parseStream(const Bit8u *stream, Bit32u length) { void MidiStreamParserImpl::processShortMessage(const Bit32u message) { // Adds running status to the MIDI message if it doesn't contain one - Bit8u status = Bit8u(message); + Bit8u status = Bit8u(message & 0xFF); if (0xF8 <= status) { midiReceiver.handleSystemRealtimeMessage(status); } else if (processStatusByte(status)) { diff --git a/src/SOUND/munt/Part.cpp b/src/SOUND/munt/Part.cpp index 85cc23970..9c85ce559 100644 --- a/src/SOUND/munt/Part.cpp +++ b/src/SOUND/munt/Part.cpp @@ -340,10 +340,13 @@ void RhythmPart::setPan(unsigned int midiPan) { void Part::setPan(unsigned int midiPan) { // NOTE: Panning is inverted compared to GM. - // CM-32L: Divide by 8.5 - patchTemp->panpot = Bit8u((midiPan << 3) / 68); - // FIXME: MT-32: Divide by 9 - //patchTemp->panpot = Bit8u(midiPan / 9); + if (synth->controlROMFeatures->quirkPanMult) { + // MT-32: Divide by 9 + patchTemp->panpot = Bit8u(midiPan / 9); + } else { + // CM-32L: Divide by 8.5 + patchTemp->panpot = Bit8u((midiPan << 3) / 68); + } //synth->printDebug("%s (%s): Set pan to %d", name, currentInstr, panpot); } @@ -352,6 +355,10 @@ void Part::setPan(unsigned int midiPan) { * Applies key shift to a MIDI key and converts it into an internal key value in the range 12-108. */ unsigned int Part::midiKeyToKey(unsigned int midiKey) { + if (synth->controlROMFeatures->quirkKeyShift) { + // NOTE: On MT-32 GEN0, key isn't adjusted, and keyShift is applied further in TVP, unlike newer units: + return midiKey; + } int key = midiKey + patchTemp->patch.keyShift; if (key < 36) { // After keyShift is applied, key < 36, so move up by octaves diff --git a/src/SOUND/munt/Partial.cpp b/src/SOUND/munt/Partial.cpp index 72a3af0ab..da5e7c4a1 100644 --- a/src/SOUND/munt/Partial.cpp +++ b/src/SOUND/munt/Partial.cpp @@ -272,6 +272,10 @@ bool Partial::isRingModulatingSlave() const { return pair != NULL && structurePosition == 1 && (mixType == 1 || mixType == 2); } +bool Partial::isRingModulatingNoMix() const { + return pair != NULL && ((structurePosition == 1 && mixType == 1) || mixType == 2); +} + bool Partial::isPCM() const { return pcmWave != NULL; } @@ -368,7 +372,7 @@ bool Partial::doProduceOutput(Sample *leftBuf, Sample *rightBuf, Bit32u length, bool Partial::produceOutput(IntSample *leftBuf, IntSample *rightBuf, Bit32u length) { if (floatMode) { - synth->printDebug("Partial: Invalid call to produceOutput()!\n", synth->getSelectedRendererType()); + synth->printDebug("Partial: Invalid call to produceOutput()! Renderer = %d\n", synth->getSelectedRendererType()); return false; } return doProduceOutput(leftBuf, rightBuf, length, static_cast(la32Pair)); @@ -376,7 +380,7 @@ bool Partial::produceOutput(IntSample *leftBuf, IntSample *rightBuf, Bit32u leng bool Partial::produceOutput(FloatSample *leftBuf, FloatSample *rightBuf, Bit32u length) { if (!floatMode) { - synth->printDebug("Partial: Invalid call to produceOutput()!\n", synth->getSelectedRendererType()); + synth->printDebug("Partial: Invalid call to produceOutput()! Renderer = %d\n", synth->getSelectedRendererType()); return false; } return doProduceOutput(leftBuf, rightBuf, length, static_cast(la32Pair)); diff --git a/src/SOUND/munt/Partial.h b/src/SOUND/munt/Partial.h index bdb65952e..95f4c3fc2 100644 --- a/src/SOUND/munt/Partial.h +++ b/src/SOUND/munt/Partial.h @@ -108,6 +108,7 @@ public: void startAbort(); void startDecayAll(); bool shouldReverb(); + bool isRingModulatingNoMix() const; bool hasRingModulatingSlave() const; bool isRingModulatingSlave() const; bool isPCM() const; diff --git a/src/SOUND/munt/ROMInfo.cpp b/src/SOUND/munt/ROMInfo.cpp index 3eef26adf..8c813a4e6 100644 --- a/src/SOUND/munt/ROMInfo.cpp +++ b/src/SOUND/munt/ROMInfo.cpp @@ -31,6 +31,7 @@ static const ROMInfo *getKnownROMInfoFromList(Bit32u index) { static const ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL}; static const ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL}; + static const ROMInfo CTRL_MT32_V2_04 = {131072, "2c16432b6c73dd2a3947cba950a0f4c19d6180eb", ROMInfo::Control, "ctrl_mt32_2_04", "MT-32 Control v2.04", ROMInfo::Full, NULL}; static const ROMInfo CTRL_CM32L_V1_00 = {65536, "73683d585cd6948cc19547942ca0e14a0319456d", ROMInfo::Control, "ctrl_cm32l_1_00", "CM-32L/LAPC-I Control v1.00", ROMInfo::Full, NULL}; static const ROMInfo CTRL_CM32L_V1_02 = {65536, "a439fbb390da38cada95a7cbb1d6ca199cd66ef8", ROMInfo::Control, "ctrl_cm32l_1_02", "CM-32L/LAPC-I Control v1.02", ROMInfo::Full, NULL}; @@ -43,6 +44,7 @@ static const ROMInfo *getKnownROMInfoFromList(Bit32u index) { &CTRL_MT32_V1_06, &CTRL_MT32_V1_07, &CTRL_MT32_BLUER, + &CTRL_MT32_V2_04, &CTRL_CM32L_V1_00, &CTRL_CM32L_V1_02, &PCM_MT32, diff --git a/src/SOUND/munt/SampleRateConverter_dummy.cpp b/src/SOUND/munt/SampleRateConverter_dummy.cpp new file mode 100644 index 000000000..84d51e736 --- /dev/null +++ b/src/SOUND/munt/SampleRateConverter_dummy.cpp @@ -0,0 +1,60 @@ +/* Copyright (C) 2015-2017 Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "SampleRateConverter.h" + +#include "Synth.h" + +using namespace MT32Emu; + +static inline void *createDelegate(Synth &synth, double targetSampleRate, SamplerateConversionQuality quality) { + return 0; +} + +AnalogOutputMode SampleRateConverter::getBestAnalogOutputMode(double targetSampleRate) { + return AnalogOutputMode_COARSE; +} + +SampleRateConverter::SampleRateConverter(Synth &useSynth, double targetSampleRate, SamplerateConversionQuality useQuality) : + synthInternalToTargetSampleRateRatio(SAMPLE_RATE / targetSampleRate), + useSynthDelegate(useSynth.getStereoOutputSampleRate() == targetSampleRate), + srcDelegate(useSynthDelegate ? &useSynth : createDelegate(useSynth, targetSampleRate, useQuality)) +{} + +SampleRateConverter::~SampleRateConverter() { +} + +void SampleRateConverter::getOutputSamples(float *buffer, unsigned int length) { + if (useSynthDelegate) { + static_cast(srcDelegate)->render(buffer, length); + return; + } +} + +void SampleRateConverter::getOutputSamples(Bit16s *outBuffer, unsigned int length) { + if (useSynthDelegate) { + static_cast(srcDelegate)->render(outBuffer, length); + return; + } +} + +double SampleRateConverter::convertOutputToSynthTimestamp(double outputTimestamp) const { + return outputTimestamp * synthInternalToTargetSampleRateRatio; +} + +double SampleRateConverter::convertSynthToOutputTimestamp(double synthTimestamp) const { + return synthTimestamp / synthInternalToTargetSampleRateRatio; +} diff --git a/src/SOUND/munt/Structures.h b/src/SOUND/munt/Structures.h index d3abf4ee7..d116aaeb4 100644 --- a/src/SOUND/munt/Structures.h +++ b/src/SOUND/munt/Structures.h @@ -184,7 +184,13 @@ struct SoundGroup { #endif struct ControlROMFeatureSet { + unsigned int quirkBasePitchOverflow : 1; unsigned int quirkPitchEnvelopeOverflow : 1; + unsigned int quirkRingModulationNoMix : 1; + unsigned int quirkTVAZeroEnvLevels : 1; + unsigned int quirkPanMult : 1; + unsigned int quirkKeyShift : 1; + unsigned int quirkTVFBaseCutoffLimit : 1; // Features below don't actually depend on control ROM version, which is used to identify hardware model unsigned int defaultReverbMT32Compatible : 1; diff --git a/src/SOUND/munt/Synth.cpp b/src/SOUND/munt/Synth.cpp index e8464fc90..f4eda5c79 100644 --- a/src/SOUND/munt/Synth.cpp +++ b/src/SOUND/munt/Synth.cpp @@ -32,25 +32,50 @@ #include "ROMInfo.h" #include "TVA.h" +#if MT32EMU_MONITOR_SYSEX > 0 +#include "mmath.h" +#endif + namespace MT32Emu { // MIDI interface data transfer rate in samples. Used to simulate the transfer delay. static const double MIDI_DATA_TRANSFER_RATE = double(SAMPLE_RATE) / 31250.0 * 8.0; // FIXME: there should be more specific feature sets for various MT-32 control ROM versions -static const ControlROMFeatureSet OLD_MT32_COMPATIBLE = { true, true, true }; -static const ControlROMFeatureSet CM32L_COMPATIBLE = { false, false, false }; +static const ControlROMFeatureSet OLD_MT32_COMPATIBLE = { + true, // quirkBasePitchOverflow + true, // quirkPitchEnvelopeOverflow + true, // quirkRingModulationNoMix + true, // quirkTVAZeroEnvLevels + true, // quirkPanMult + true, // quirkKeyShift + true, // quirkTVFBaseCutoffLimit + true, // defaultReverbMT32Compatible + true // oldMT32AnalogLPF +}; +static const ControlROMFeatureSet CM32L_COMPATIBLE = { + false, // quirkBasePitchOverflow + false, // quirkPitchEnvelopeOverflow + false, // quirkRingModulationNoMix + false, // quirkTVAZeroEnvLevels + false, // quirkPanMult + false, // quirkKeyShift + false, // quirkTVFBaseCutoffLimit + false, // defaultReverbMT32Compatible + false // oldMT32AnalogLPF +}; -static const ControlROMMap ControlROMMaps[7] = { +static const ControlROMMap ControlROMMaps[8] = { // ID Features PCMmap PCMc tmbrA tmbrAO, tmbrAC tmbrB tmbrBO tmbrBC tmbrR trC rhythm rhyC rsrv panpot prog rhyMax patMax sysMax timMax sndGrp sGC { "ctrl_mt32_1_04", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x7064, 19 }, { "ctrl_mt32_1_05", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x70CA, 19 }, { "ctrl_mt32_1_06", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57F4, 0x57E2, 0x5264, 0x5270, 0x5280, 0x521C, 0x70CA, 19 }, { "ctrl_mt32_1_07", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57CC, 0x57BA, 0x523C, 0x5248, 0x5258, 0x51F4, 0x70B0, 19 }, // MT-32 revision 1 {"ctrl_mt32_bluer", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x741C, 85, 0x57E5, 0x5800, 0x57EE, 0x5270, 0x527C, 0x528C, 0x5228, 0x70CE, 19 }, // MT-32 Blue Ridge mod + {"ctrl_mt32_2_04", CM32L_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 30, 0x8580, 85, 0x4F5D, 0x4F78, 0x4F66, 0x4899, 0x489D, 0x48B6, 0x48CD, 0x5A58, 19 }, {"ctrl_cm32l_1_00", CM32L_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F65, 0x4F80, 0x4F6E, 0x48A1, 0x48A5, 0x48BE, 0x48D5, 0x5A6C, 19 }, {"ctrl_cm32l_1_02", CM32L_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4FAE, 0x4F9C, 0x48CB, 0x48CF, 0x48E8, 0x48FF, 0x5A96, 19 } // CM-32L - // (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp) + // (Note that old MT-32 ROMs actually have 86 entries for rhythmTemp) }; static const PartialState PARTIAL_PHASE_TO_STATE[8] = { @@ -78,7 +103,7 @@ protected: Synth &synth; void printDebug(const char *msg) const { - synth.printDebug(msg); + synth.printDebug("%s", msg); } bool isActivated() const { @@ -168,6 +193,8 @@ public: class Extensions { public: RendererType selectedRendererType; + Bit32s masterTunePitchDelta; + bool niceAmpRamp; }; Bit32u Synth::getLibraryVersionInt() { @@ -222,6 +249,7 @@ Synth::Synth(ReportHandler *useReportHandler) : setOutputGain(1.0f); setReverbOutputGain(1.0f); setReversedStereoEnabled(false); + setNiceAmpRampEnabled(true); selectRendererType(RendererType_BIT16S); patchTempMemoryRegion = NULL; @@ -387,6 +415,14 @@ bool Synth::isReversedStereoEnabled() const { return reversedStereoEnabled; } +void Synth::setNiceAmpRampEnabled(bool enabled) { + extensions.niceAmpRamp = enabled; +} + +bool Synth::isNiceAmpRampEnabled() const { + return extensions.niceAmpRamp; +} + bool Synth::loadControlROM(const ROMImage &controlROMImage) { File *file = controlROMImage.getFile(); const ROMInfo *controlROMInfo = controlROMImage.getROMInfo(); @@ -679,6 +715,7 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B bool oldReverbOverridden = reverbOverridden; reverbOverridden = false; refreshSystem(); + resetMasterTunePitchDelta(); reverbOverridden = oldReverbOverridden; char(*writableSoundGroupNames)[9] = new char[controlROMMap->soundGroupsCount][9]; @@ -865,13 +902,17 @@ Bit32u Synth::addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp) { return timestamp; } +Bit32u Synth::getInternalRenderedSampleCount() const { + return renderedSampleCount; +} + bool Synth::playMsg(Bit32u msg) { return playMsg(msg, renderedSampleCount); } bool Synth::playMsg(Bit32u msg, Bit32u timestamp) { if ((msg & 0xF8) == 0xF8) { - reportHandler->onMIDISystemRealtime(Bit8u(msg)); + reportHandler->onMIDISystemRealtime(Bit8u(msg & 0xFF)); return true; } if (midiQueue == NULL) return false; @@ -1539,6 +1580,8 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le } void Synth::refreshSystemMasterTune() { + // 171 is ~half a semitone. + extensions.masterTunePitchDelta = ((mt32ram.system.masterTune - 64) * 171) >> 6; // PORTABILITY NOTE: Assumes arithmetic shift. #if MT32EMU_MONITOR_SYSEX > 0 //FIXME:KG: This is just an educated guess. // The LAPC-I documentation claims a range of 427.5Hz-452.6Hz (similar to what we have here) @@ -1650,9 +1693,25 @@ void Synth::reset() { } } refreshSystem(); + resetMasterTunePitchDelta(); isActive(); } +void Synth::resetMasterTunePitchDelta() { + // This effectively resets master tune to 440.0Hz. + // Despite that the manual claims 442.0Hz is the default setting for master tune, + // it doesn't actually take effect upon a reset due to a bug in the reset routine. + // CONFIRMED: This bug is present in all supported Control ROMs. + extensions.masterTunePitchDelta = 0; +#if MT32EMU_MONITOR_SYSEX > 0 + printDebug(" Actual Master Tune reset to 440.0"); +#endif +} + +Bit32s Synth::getMasterTunePitchDelta() const { + return extensions.masterTunePitchDelta; +} + MidiEvent::~MidiEvent() { if (sysexData != NULL) { delete[] sysexData; @@ -2013,21 +2072,35 @@ void RendererImpl::convertSamplesToOutput(IntSample *buffer, Bit32u l } static inline float produceDistortedSample(float sample) { - if (sample < -2.0f) { - return sample + 4.0f; - } else if (2.0f < sample) { - return sample - 4.0f; + // Here we roughly simulate the distortion caused by the DAC bit shift. + if (sample < -1.0f) { + return sample + 2.0f; + } else if (1.0f < sample) { + return sample - 2.0f; } return sample; } template <> void RendererImpl::produceLA32Output(FloatSample *buffer, Bit32u len) { - if (synth.getDACInputMode() == DACInputMode_GENERATION2) { + switch (synth.getDACInputMode()) { + case DACInputMode_NICE: + // Note, we do not do any clamping for floats here to avoid introducing distortions. + // This means that the output signal may actually overshoot the unity when the volume is set too high. + // We leave it up to the consumer whether the output is to be clamped or properly normalised further on. while (len--) { - *buffer = produceDistortedSample(*buffer); + *buffer *= 2.0f; buffer++; } + break; + case DACInputMode_GENERATION2: + while (len--) { + *buffer = produceDistortedSample(2.0f * *buffer); + buffer++; + } + break; + default: + break; } } @@ -2035,7 +2108,7 @@ template <> void RendererImpl::convertSamplesToOutput(FloatSample *buffer, Bit32u len) { if (synth.getDACInputMode() == DACInputMode_GENERATION1) { while (len--) { - *buffer = produceDistortedSample(*buffer); + *buffer = produceDistortedSample(2.0f * *buffer); buffer++; } } diff --git a/src/SOUND/munt/Synth.h b/src/SOUND/munt/Synth.h index 4ce023201..cde080c9d 100644 --- a/src/SOUND/munt/Synth.h +++ b/src/SOUND/munt/Synth.h @@ -124,6 +124,7 @@ friend class RhythmPart; friend class SamplerateAdapter; friend class SoxrAdapter; friend class TVA; +friend class TVF; friend class TVP; private: @@ -230,6 +231,9 @@ private: // partNum should be 0..7 for Part 1..8, or 8 for Rhythm const Part *getPart(Bit8u partNum) const; + void resetMasterTunePitchDelta(); + Bit32s getMasterTunePitchDelta() const; + public: static inline Bit16s clipSampleEx(Bit32s sampleEx) { // Clamp values above 32767 to 32767, and values below -32768 to -32768 @@ -258,11 +262,11 @@ public: } static inline Bit16s convertSample(float sample) { - return Synth::clipSampleEx(Bit32s(sample * 16384.0f)); // This multiplier takes into account the DAC bit shift + return Synth::clipSampleEx(Bit32s(sample * 32768.0f)); // This multiplier corresponds to normalised floats } static inline float convertSample(Bit16s sample) { - return float(sample) / 16384.0f; // This multiplier takes into account the DAC bit shift + return float(sample) / 32768.0f; // This multiplier corresponds to normalised floats } // Returns library version as an integer in format: 0x00MMmmpp, where: @@ -308,6 +312,10 @@ public: // Returns the actual queue size being used. MT32EMU_EXPORT Bit32u setMIDIEventQueueSize(Bit32u); + // Returns current value of the global counter of samples rendered since the synth was created (at the native sample rate 32000 Hz). + // This method helps to compute accurate timestamp of a MIDI message to use with the methods below. + MT32EMU_EXPORT Bit32u getInternalRenderedSampleCount() const; + // Enqueues a MIDI event for subsequent playback. // The MIDI event will be processed not before the specified timestamp. // The timestamp is measured as the global rendered sample count since the synth was created (at the native sample rate 32000 Hz). @@ -382,7 +390,6 @@ public: // Sets output gain factor for synth output channels. Applied to all output samples and unrelated with the synth's Master volume, // it rather corresponds to the gain of the output analog circuitry of the hardware units. However, together with setReverbOutputGain() // it offers to the user a capability to control the gain of reverb and non-reverb output channels independently. - // Ignored in DACInputMode_PURE MT32EMU_EXPORT void setOutputGain(float gain); // Returns current output gain factor for synth output channels. MT32EMU_EXPORT float getOutputGain() const; @@ -395,7 +402,6 @@ public: // corresponds to the level of digital capture. Although, according to the CM-64 PCB schematic, // there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68 // of that for LA32 analogue output. This factor is applied to the reverb output gain. - // Ignored in DACInputMode_PURE MT32EMU_EXPORT void setReverbOutputGain(float gain); // Returns current output gain factor for reverb wet output channels. MT32EMU_EXPORT float getReverbOutputGain() const; @@ -405,6 +411,16 @@ public: // Returns whether left and right output channels are swapped. MT32EMU_EXPORT bool isReversedStereoEnabled() const; + // Allows to toggle the NiceAmpRamp mode. + // In this mode, we want to ensure that amp ramp never jumps to the target + // value and always gradually increases or decreases. It seems that real units + // do not bother to always check if a newly started ramp leads to a jump. + // We also prefer the quality improvement over the emulation accuracy, + // so this mode is enabled by default. + MT32EMU_EXPORT void setNiceAmpRampEnabled(bool enabled); + // Returns whether NiceAmpRamp mode is enabled. + MT32EMU_EXPORT bool isNiceAmpRampEnabled() const; + // Selects new type of the wave generator and renderer to be used during subsequent calls to open(). // By default, RendererType_BIT16S is selected. // See RendererType for details. diff --git a/src/SOUND/munt/TVA.cpp b/src/SOUND/munt/TVA.cpp index d75abe50a..3f7064f9a 100644 --- a/src/SOUND/munt/TVA.cpp +++ b/src/SOUND/munt/TVA.cpp @@ -43,7 +43,7 @@ void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) { phase = newPhase; ampRamp->startRamp(newTarget, newIncrement); #if MT32EMU_MONITOR_TVA >= 1 - partial->getSynth()->printDebug("[+%lu] [Partial %d] TVA,ramp,%d,%d,%d,%d", partial->debugGetSampleNum(), partial->debugGetPartialNum(), (newIncrement & 0x80) ? -1 : 1, (newIncrement & 0x7F), newPhase); + partial->getSynth()->printDebug("[+%lu] [Partial %d] TVA,ramp,%x,%s%x,%d", partial->debugGetSampleNum(), partial->debugGetPartialNum(), newTarget, (newIncrement & 0x80) ? "-" : "+", (newIncrement & 0x7F), newPhase); #endif } @@ -99,10 +99,10 @@ static int calcVeloAmpSubtraction(Bit8u veloSensitivity, unsigned int velocity) return absVelocityMult - (velocityMult >> 8); // PORTABILITY NOTE: Assumes arithmetic shift } -static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemParams::System *system, const TimbreParam::PartialParam *partialParam, const MemParams::PatchTemp *patchTemp, const MemParams::RhythmTemp *rhythmTemp, int biasAmpSubtraction, int veloAmpSubtraction, Bit8u expression) { +static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemParams::System *system, const TimbreParam::PartialParam *partialParam, const MemParams::PatchTemp *patchTemp, const MemParams::RhythmTemp *rhythmTemp, int biasAmpSubtraction, int veloAmpSubtraction, Bit8u expression, bool hasRingModQuirk) { int amp = 155; - if (!partial->isRingModulatingSlave()) { + if (!(hasRingModQuirk ? partial->isRingModulatingNoMix() : partial->isRingModulatingSlave())) { amp -= tables->masterVolToAmpSubtraction[system->masterVol]; if (amp < 0) { return 0; @@ -169,7 +169,7 @@ void TVA::reset(const Part *newPart, const TimbreParam::PartialParam *newPartial biasAmpSubtraction = calcBiasAmpSubtractions(partialParam, key); veloAmpSubtraction = calcVeloAmpSubtraction(partialParam->tva.veloSensitivity, velocity); - int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, newRhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression()); + int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, newRhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); int newPhase; if (partialParam->tva.envTime[0] == 0) { // Initially go to the TVA_PHASE_ATTACK target amp, and spend the next phase going from there to the TVA_PHASE_2 target amp @@ -221,18 +221,29 @@ void TVA::recalcSustain() { } // We're sustaining. Recalculate all the values const Tables *tables = &Tables::getInstance(); - int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression()); + int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); newTarget += partialParam->tva.envLevel[3]; - // Since we're in TVA_PHASE_SUSTAIN at this point, we know that target has been reached and an interrupt fired, so we can rely on it being the current amp. + + // Although we're in TVA_PHASE_SUSTAIN at this point, we cannot be sure that there is no active ramp at the moment. + // In case the channel volume or the expression changes frequently, the previously started ramp may still be in progress. + // Real hardware units ignore this possibility and rely on the assumption that the target is the current amp. + // This is OK in most situations but when the ramp that is currently in progress needs to change direction + // due to a volume/expression update, this leads to a jump in the amp that is audible as an unpleasant click. + // To avoid that, we compare the newTarget with the the actual current ramp value and correct the direction if necessary. int targetDelta = newTarget - target; // Calculate an increment to get to the new amp value in a short, more or less consistent amount of time Bit8u newIncrement; - if (targetDelta >= 0) { + bool descending = targetDelta < 0; + if (!descending) { newIncrement = tables->envLogarithmicTime[Bit8u(targetDelta)] - 2; } else { newIncrement = (tables->envLogarithmicTime[Bit8u(-targetDelta)] - 2) | 0x80; } + if (part->getSynth()->isNiceAmpRampEnabled() && (descending != ampRamp->isBelowCurrent(newTarget))) { + newIncrement ^= 0x80; + } + // Configure so that once the transition's complete and nextPhase() is called, we'll just re-enter sustain phase (or decay phase, depending on parameters at the time). startRamp(newTarget, newIncrement, TVA_PHASE_SUSTAIN - 1); } @@ -260,7 +271,7 @@ void TVA::nextPhase() { } bool allLevelsZeroFromNowOn = false; - if (partialParam->tva.envLevel[3] == 0) { + if (!partial->getSynth()->controlROMFeatures->quirkTVAZeroEnvLevels && partialParam->tva.envLevel[3] == 0) { if (newPhase == TVA_PHASE_4) { allLevelsZeroFromNowOn = true; } else if (partialParam->tva.envLevel[2] == 0) { @@ -283,7 +294,7 @@ void TVA::nextPhase() { int envPointIndex = phase; if (!allLevelsZeroFromNowOn) { - newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression()); + newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); if (newPhase == TVA_PHASE_SUSTAIN || newPhase == TVA_PHASE_RELEASE) { if (partialParam->tva.envLevel[3] == 0) { diff --git a/src/SOUND/munt/TVF.cpp b/src/SOUND/munt/TVF.cpp index cafeb4a8d..7ba9c7f2e 100644 --- a/src/SOUND/munt/TVF.cpp +++ b/src/SOUND/munt/TVF.cpp @@ -21,6 +21,7 @@ #include "LA32Ramp.h" #include "Partial.h" #include "Poly.h" +#include "Synth.h" #include "Tables.h" namespace MT32Emu { @@ -52,7 +53,7 @@ enum { PHASE_DONE = 7 }; -static int calcBaseCutoff(const TimbreParam::PartialParam *partialParam, Bit32u basePitch, unsigned int key) { +static int calcBaseCutoff(const TimbreParam::PartialParam *partialParam, Bit32u basePitch, unsigned int key, bool quirkTVFBaseCutoffLimit) { // This table matches the values used by a real LAPC-I. static const Bit8s biasLevelToBiasMult[] = {85, 42, 21, 16, 10, 5, 2, 0, -2, -5, -10, -16, -21, -74, -85}; // These values represent unique options with no consistent pattern, so we have to use something like a table in any case. @@ -90,8 +91,14 @@ static int calcBaseCutoff(const TimbreParam::PartialParam *partialParam, Bit32u if (pitchDeltaThing > 0) { baseCutoff -= pitchDeltaThing; } - } else if (baseCutoff < -2048) { - baseCutoff = -2048; + } else if (quirkTVFBaseCutoffLimit) { + if (baseCutoff <= -0x400) { + baseCutoff = -400; + } + } else { + if (baseCutoff < -2048) { + baseCutoff = -2048; + } } baseCutoff += 2056; baseCutoff >>= 4; // PORTABILITY NOTE: Hmm... Depends whether it could've been below -2056, but maybe arithmetic shift assumed? @@ -110,7 +117,7 @@ void TVF::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) { phase = newPhase; cutoffModifierRamp->startRamp(newTarget, newIncrement); #if MT32EMU_MONITOR_TVF >= 1 - partial->getSynth()->printDebug("[+%lu] [Partial %d] TVF,ramp,%d,%d,%d,%d", partial->debugGetSampleNum(), partial->debugGetPartialNum(), newTarget, (newIncrement & 0x80) ? -1 : 1, (newIncrement & 0x7F), newPhase); + partial->getSynth()->printDebug("[+%lu] [Partial %d] TVF,ramp,%x,%s%x,%d", partial->debugGetSampleNum(), partial->debugGetPartialNum(), newTarget, (newIncrement & 0x80) ? "-" : "+", (newIncrement & 0x7F), newPhase); #endif } @@ -122,7 +129,7 @@ void TVF::reset(const TimbreParam::PartialParam *newPartialParam, unsigned int b const Tables *tables = &Tables::getInstance(); - baseCutoff = calcBaseCutoff(newPartialParam, basePitch, key); + baseCutoff = calcBaseCutoff(newPartialParam, basePitch, key, partial->getSynth()->controlROMFeatures->quirkTVFBaseCutoffLimit); #if MT32EMU_MONITOR_TVF >= 1 partial->getSynth()->printDebug("[+%lu] [Partial %d] TVF,base,%d", partial->debugGetSampleNum(), partial->debugGetPartialNum(), baseCutoff); #endif diff --git a/src/SOUND/munt/TVP.cpp b/src/SOUND/munt/TVP.cpp index 9adedf851..a3b364048 100644 --- a/src/SOUND/munt/TVP.cpp +++ b/src/SOUND/munt/TVP.cpp @@ -51,13 +51,15 @@ static Bit16u keyToPitchTable[] = { 21845, 22187, 22528, 22869 }; +// We want to do processing 4000 times per second. FIXME: This is pretty arbitrary. +static const int NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES = SAMPLE_RATE / 4000; + +// The timer runs at 500kHz. This is how much to increment it after 8 samples passes. +// We multiply by 8 to get rid of the fraction and deal with just integers. +static const int PROCESS_TIMER_INCREMENT_x8 = 8 * 500000 / SAMPLE_RATE; + TVP::TVP(const Partial *usePartial) : partial(usePartial), system(&usePartial->getSynth()->mt32ram.system) { - // We want to do processing 4000 times per second. FIXME: This is pretty arbitrary. - maxCounter = SAMPLE_RATE / 4000; - // The timer runs at 500kHz. We only need to bother updating it every maxCounter samples, before we do processing. - // This is how much to increment it by every maxCounter samples. - processTimerIncrement = 500000 * maxCounter / SAMPLE_RATE; } static Bit16s keyToPitch(unsigned int key) { @@ -76,13 +78,15 @@ static inline Bit32s fineToPitch(Bit8u fine) { return (fine - 50) * 4096 / 1200; // One cent per fine offset } -static Bit32u calcBasePitch(const Partial *partial, const TimbreParam::PartialParam *partialParam, const MemParams::PatchTemp *patchTemp, unsigned int key) { +static Bit32u calcBasePitch(const Partial *partial, const TimbreParam::PartialParam *partialParam, const MemParams::PatchTemp *patchTemp, unsigned int key, const ControlROMFeatureSet *controlROMFeatures) { Bit32s basePitch = keyToPitch(key); basePitch = (basePitch * pitchKeyfollowMult[partialParam->wg.pitchKeyfollow]) >> 13; // PORTABILITY NOTE: Assumes arithmetic shift basePitch += coarseToPitch(partialParam->wg.pitchCoarse); basePitch += fineToPitch(partialParam->wg.pitchFine); - // NOTE:Mok: This is done on MT-32, but not LAPC-I: - //pitch += coarseToPitch(patchTemp->patch.keyShift + 12); + if (controlROMFeatures->quirkKeyShift) { + // NOTE:Mok: This is done on MT-32, but not LAPC-I: + basePitch += coarseToPitch(patchTemp->patch.keyShift + 12); + } basePitch += fineToPitch(patchTemp->patch.fineTune); const ControlROMPCMStruct *controlROMPCMStruct = partial->getControlROMPCMStruct(); @@ -97,7 +101,12 @@ static Bit32u calcBasePitch(const Partial *partial, const TimbreParam::PartialPa basePitch += 33037; } } - if (basePitch < 0) { + + // MT-32 GEN0 does 16-bit calculations here, allowing an integer overflow. + // This quirk is observable playing the patch defined for timbre "HIT BOTTOM" in Larry 3. + if (controlROMFeatures->quirkBasePitchOverflow) { + basePitch = basePitch & 0xffff; + } else if (basePitch < 0) { basePitch = 0; } if (basePitch > 59392) { @@ -107,18 +116,22 @@ static Bit32u calcBasePitch(const Partial *partial, const TimbreParam::PartialPa } static Bit32u calcVeloMult(Bit8u veloSensitivity, unsigned int velocity) { - if (veloSensitivity == 0 || veloSensitivity > 3) { - // Note that on CM-32L/LAPC-I veloSensitivity is never > 3, since it's clipped to 3 by the max tables. + if (veloSensitivity == 0) { return 21845; // aka floor(4096 / 12 * 64), aka ~64 semitones } + unsigned int reversedVelocity = 127 - velocity; + unsigned int scaledReversedVelocity; + if (veloSensitivity > 3) { + // Note that on CM-32L/LAPC-I veloSensitivity is never > 3, since it's clipped to 3 by the max tables. + // MT-32 GEN0 has a bug here that leads to unspecified behaviour. We assume it is as follows. + scaledReversedVelocity = (reversedVelocity << 8) >> ((3 - veloSensitivity) & 0x1f); + } else { + scaledReversedVelocity = reversedVelocity << (5 + veloSensitivity); + } // When velocity is 127, the multiplier is 21845, aka ~64 semitones (regardless of veloSensitivity). // The lower the velocity, the lower the multiplier. The veloSensitivity determines the amount decreased per velocity value. - // The minimum multiplier (with velocity 0, veloSensitivity 3) is 170 (~half a semitone). - Bit32u veloMult = 32768; - veloMult -= (127 - velocity) << (5 + veloSensitivity); - veloMult *= 21845; - veloMult >>= 15; - return veloMult; + // The minimum multiplier on CM-32L/LAPC-I (with velocity 0, veloSensitivity 3) is 170 (~half a semitone). + return ((32768 - scaledReversedVelocity) * 21845) >> 15; } static Bit32s calcTargetPitchOffsetWithoutLFO(const TimbreParam::PartialParam *partialParam, int levelIndex, unsigned int velocity) { @@ -139,7 +152,7 @@ void TVP::reset(const Part *usePart, const TimbreParam::PartialParam *usePartial // FIXME: We're using a per-TVP timer instead of a system-wide one for convenience. timeElapsed = 0; - basePitch = calcBasePitch(partial, partialParam, patchTemp, key); + basePitch = calcBasePitch(partial, partialParam, patchTemp, key, partial->getSynth()->controlROMFeatures); currentPitchOffset = calcTargetPitchOffsetWithoutLFO(partialParam, 0, velocity); targetPitchOffsetWithoutLFO = currentPitchOffset; phase = 0; @@ -166,22 +179,23 @@ Bit32u TVP::getBasePitch() const { void TVP::updatePitch() { Bit32s newPitch = basePitch + currentPitchOffset; if (!partial->isPCM() || (partial->getControlROMPCMStruct()->len & 0x01) == 0) { // FIXME: Use !partial->pcmWaveEntry->unaffectedByMasterTune instead - // FIXME: masterTune recalculation doesn't really happen here, and there are various bugs not yet emulated + // FIXME: There are various bugs not yet emulated // 171 is ~half a semitone. - newPitch += ((system->masterTune - 64) * 171) >> 6; // PORTABILITY NOTE: Assumes arithmetic shift. + newPitch += partial->getSynth()->getMasterTunePitchDelta(); } if ((partialParam->wg.pitchBenderEnabled & 1) != 0) { newPitch += part->getPitchBend(); } - if (newPitch < 0) { + + // MT-32 GEN0 does 16-bit calculations here, allowing an integer overflow. + // This quirk is exploited e.g. in Colonel's Bequest timbres "Lightning" and "SwmpBackgr". + if (partial->getSynth()->controlROMFeatures->quirkPitchEnvelopeOverflow) { + newPitch = newPitch & 0xffff; + } else if (newPitch < 0) { newPitch = 0; } - - // Skipping this check seems about right emulation of MT-32 GEN0 quirk exploited in Colonel's Bequest timbre "Lightning" - if (partial->getSynth()->controlROMFeatures->quirkPitchEnvelopeOverflow == 0) { - if (newPitch > 59392) { - newPitch = 59392; - } + if (newPitch > 59392) { + newPitch = 59392; } pitch = Bit16u(newPitch); @@ -284,13 +298,19 @@ void TVP::startDecay() { } Bit16u TVP::nextPitch() { - // FIXME: Write explanation of counter and time increment + // We emulate MCU software timer using these counter and processTimerIncrement variables. + // The value of nominalProcessTimerPeriod approximates the period in samples + // between subsequent firings of the timer that normally occur. + // However, accurate emulation is quite complicated because the timer is not guaranteed to fire in time. + // This makes pitch variations on real unit non-deterministic and dependent on various factors. if (counter == 0) { - timeElapsed += processTimerIncrement; - timeElapsed = timeElapsed & 0x00FFFFFF; + timeElapsed = (timeElapsed + processTimerIncrement) & 0x00FFFFFF; + // This roughly emulates pitch deviations observed on real units when playing a single partial that uses TVP/LFO. + counter = NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES + (rand() & 3); + processTimerIncrement = (PROCESS_TIMER_INCREMENT_x8 * counter) >> 3; process(); } - counter = (counter + 1) % maxCounter; + counter--; return pitch; } diff --git a/src/SOUND/munt/TVP.h b/src/SOUND/munt/TVP.h index 55f89c5f4..896e8c11a 100644 --- a/src/SOUND/munt/TVP.h +++ b/src/SOUND/munt/TVP.h @@ -36,7 +36,6 @@ private: const TimbreParam::PartialParam *partialParam; const MemParams::PatchTemp *patchTemp; - int maxCounter; int processTimerIncrement; int counter; Bit32u timeElapsed; diff --git a/src/SOUND/munt/c_interface/c_interface.cpp b/src/SOUND/munt/c_interface/c_interface.cpp index 9028c2612..24bb1460e 100644 --- a/src/SOUND/munt/c_interface/c_interface.cpp +++ b/src/SOUND/munt/c_interface/c_interface.cpp @@ -22,6 +22,7 @@ #include "../ROMInfo.h" #include "../Synth.h" #include "../MidiStreamParser.h" +#include "../SampleRateConverter.h" #include "c_types.h" #include "c_interface.h" @@ -30,11 +31,17 @@ using namespace MT32Emu; namespace MT32Emu { +struct SamplerateConversionState { + double outputSampleRate; + SamplerateConversionQuality srcQuality; + SampleRateConverter *src; +}; + static mt32emu_service_version getSynthVersionID(mt32emu_service_i) { return MT32EMU_SERVICE_VERSION_CURRENT; } -static const mt32emu_service_i_v0 SERVICE_VTABLE = { +static const mt32emu_service_i_v2 SERVICE_VTABLE = { getSynthVersionID, mt32emu_get_supported_report_handler_version, mt32emu_get_supported_midi_receiver_version, @@ -95,7 +102,17 @@ static const mt32emu_service_i_v0 SERVICE_VTABLE = { mt32emu_get_partial_states, mt32emu_get_playing_notes, mt32emu_get_patch_name, - mt32emu_read_memory + mt32emu_read_memory, + mt32emu_get_best_analog_output_mode, + mt32emu_set_stereo_output_samplerate, + mt32emu_set_samplerate_conversion_quality, + mt32emu_select_renderer_type, + mt32emu_get_selected_renderer_type, + mt32emu_convert_output_to_synth_timestamp, + mt32emu_convert_synth_to_output_timestamp, + mt32emu_get_internal_rendered_sample_count, + mt32emu_set_nice_amp_ramp_enabled, + mt32emu_is_nice_amp_ramp_enabled }; } // namespace MT32Emu @@ -108,6 +125,7 @@ struct mt32emu_data { DefaultMidiStreamParser *midiParser; Bit32u partialCount; AnalogOutputMode analogOutputMode; + SamplerateConversionState *srcState; }; // Internal C++ utility stuff @@ -305,7 +323,7 @@ extern "C" { mt32emu_service_i mt32emu_get_service_i() { mt32emu_service_i i; - i.v0 = &SERVICE_VTABLE; + i.v2 = &SERVICE_VTABLE; return i; } @@ -329,6 +347,10 @@ mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_ return Synth::getStereoOutputSampleRate(static_cast(analog_output_mode)); } +mt32emu_analog_output_mode mt32emu_get_best_analog_output_mode(const double target_samplerate) { + return mt32emu_analog_output_mode(SampleRateConverter::getBestAnalogOutputMode(target_samplerate)); +} + mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data) { mt32emu_data *data = new mt32emu_data; data->reportHandler = (report_handler.v0 != NULL) ? new DelegatingReportHandlerAdapter(report_handler, instance_data) : new ReportHandler; @@ -339,12 +361,22 @@ mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, data->partialCount = DEFAULT_MAX_PARTIALS; data->analogOutputMode = AnalogOutputMode_COARSE; + data->srcState = new SamplerateConversionState; + data->srcState->outputSampleRate = 0.0; + data->srcState->srcQuality = SamplerateConversionQuality_GOOD; + data->srcState->src = NULL; + return data; } void mt32emu_free_context(mt32emu_context data) { if (data == NULL) return; + delete data->srcState->src; + data->srcState->src = NULL; + delete data->srcState; + data->srcState = NULL; + if (data->controlROMImage != NULL) { delete data->controlROMImage->getFile(); ROMImage::freeROMImage(data->controlROMImage); @@ -417,6 +449,16 @@ void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analo context->analogOutputMode = static_cast(analog_output_mode); } +void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate) { + if (0.0 <= samplerate) { + context->srcState->outputSampleRate = samplerate; + } +} + +void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality) { + context->srcState->srcQuality = SamplerateConversionQuality(quality); +} + void mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type) { context->synth->selectRendererType(static_cast(renderer_type)); } @@ -432,11 +474,16 @@ mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context) { if (!context->synth->open(*context->controlROMImage, *context->pcmROMImage, context->partialCount, context->analogOutputMode)) { return MT32EMU_RC_FAILED; } + SamplerateConversionState &srcState = *context->srcState; + const double outputSampleRate = (0.0 < srcState.outputSampleRate) ? srcState.outputSampleRate : context->synth->getStereoOutputSampleRate(); + srcState.src = new SampleRateConverter(*context->synth, outputSampleRate, srcState.srcQuality); return MT32EMU_RC_OK; } void mt32emu_close_synth(mt32emu_const_context context) { context->synth->close(); + delete context->srcState->src; + context->srcState->src = NULL; } mt32emu_boolean mt32emu_is_open(mt32emu_const_context context) { @@ -444,7 +491,24 @@ mt32emu_boolean mt32emu_is_open(mt32emu_const_context context) { } mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context) { - return context->synth->getStereoOutputSampleRate(); + if (context->srcState->src == NULL) { + return context->synth->getStereoOutputSampleRate(); + } + return mt32emu_bit32u(0.5 + context->srcState->src->convertSynthToOutputTimestamp(SAMPLE_RATE)); +} + +mt32emu_bit32u mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp) { + if (context->srcState->src == NULL) { + return output_timestamp; + } + return mt32emu_bit32u(0.5 + context->srcState->src->convertOutputToSynthTimestamp(output_timestamp)); +} + +mt32emu_bit32u mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp) { + if (context->srcState->src == NULL) { + return synth_timestamp; + } + return mt32emu_bit32u(0.5 + context->srcState->src->convertSynthToOutputTimestamp(synth_timestamp)); } void mt32emu_flush_midi_queue(mt32emu_const_context context) { @@ -460,6 +524,10 @@ void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i context->midiParser = (midi_receiver.v0 != NULL) ? new DelegatingMidiStreamParser(context, midi_receiver, instance_data) : new DefaultMidiStreamParser(*context->synth); } +mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context) { + return context->synth->getInternalRenderedSampleCount(); +} + void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length) { context->midiParser->resetTimestamp(); context->midiParser->parseStream(stream, length); @@ -584,12 +652,28 @@ mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context return context->synth->isReversedStereoEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } +void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { + context->synth->setNiceAmpRampEnabled(enabled != MT32EMU_BOOL_FALSE); +} + +mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context) { + return context->synth->isNiceAmpRampEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; +} + void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) { - context->synth->render(stream, len); + if (context->srcState->src != NULL) { + context->srcState->src->getOutputSamples(stream, len); + } else { + context->synth->render(stream, len); + } } void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len) { - context->synth->render(stream, len); + if (context->srcState->src != NULL) { + context->srcState->src->getOutputSamples(stream, len); + } else { + context->synth->render(stream, len); + } } void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len) { diff --git a/src/SOUND/munt/c_interface/c_interface.h b/src/SOUND/munt/c_interface/c_interface.h index 09c004b0d..2ca3a3b04 100644 --- a/src/SOUND/munt/c_interface/c_interface.h +++ b/src/SOUND/munt/c_interface/c_interface.h @@ -209,6 +209,12 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_co */ MT32EMU_EXPORT void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); +/** + * Returns current value of the global counter of samples rendered since the synth was created (at the native sample rate 32000 Hz). + * This method helps to compute accurate timestamp of a MIDI message to use with the methods below. + */ +MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context); + /* Enqueues a MIDI event for subsequent playback. * The MIDI event will be processed not before the specified timestamp. * The timestamp is measured as the global rendered sample count since the synth was created (at the native sample rate 32000 Hz). @@ -324,7 +330,6 @@ MT32EMU_EXPORT mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const * Sets output gain factor for synth output channels. Applied to all output samples and unrelated with the synth's Master volume, * it rather corresponds to the gain of the output analog circuitry of the hardware units. However, together with mt32emu_set_reverb_output_gain() * it offers to the user a capability to control the gain of reverb and non-reverb output channels independently. - * Ignored in MT32EMU_DAC_PURE mode. */ MT32EMU_EXPORT void mt32emu_set_output_gain(mt32emu_const_context context, float gain); /** Returns current output gain factor for synth output channels. */ @@ -339,7 +344,6 @@ MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context); * corresponds to the level of digital capture. Although, according to the CM-64 PCB schematic, * there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68 * of that for LA32 analogue output. This factor is applied to the reverb output gain. - * Ignored in MT32EMU_DAC_PURE mode. */ MT32EMU_EXPORT void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain); /** Returns current output gain factor for reverb wet output channels. */ @@ -350,6 +354,18 @@ MT32EMU_EXPORT void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context co /** Returns whether left and right output channels are swapped. */ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context); +/** + * Allows to toggle the NiceAmpRamp mode. + * In this mode, we want to ensure that amp ramp never jumps to the target + * value and always gradually increases or decreases. It seems that real units + * do not bother to always check if a newly started ramp leads to a jump. + * We also prefer the quality improvement over the emulation accuracy, + * so this mode is enabled by default. + */ +MT32EMU_EXPORT void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +/** Returns whether NiceAmpRamp mode is enabled. */ +MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context); + /** * Renders samples to the specified output stream as if they were sampled at the analog stereo output at the desired sample rate. * If the output sample rate is not specified explicitly, the default output sample rate is used which depends on the current diff --git a/src/SOUND/munt/c_interface/c_types.h b/src/SOUND/munt/c_interface/c_types.h index bf4dab8dc..db612e282 100644 --- a/src/SOUND/munt/c_interface/c_types.h +++ b/src/SOUND/munt/c_interface/c_types.h @@ -120,7 +120,8 @@ typedef enum { typedef enum { MT32EMU_SERVICE_VERSION_0 = 0, MT32EMU_SERVICE_VERSION_1 = 1, - MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_1 + MT32EMU_SERVICE_VERSION_2 = 2, + MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_2 } mt32emu_service_version; /* === Report Handler Interface === */ @@ -297,6 +298,11 @@ typedef union mt32emu_service_i mt32emu_service_i; mt32emu_bit32u (*convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \ mt32emu_bit32u (*convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); +#define MT32EMU_SERVICE_I_V2 \ + mt32emu_bit32u (*getInternalRenderedSampleCount)(mt32emu_const_context context); \ + void (*setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (*isNiceAmpRampEnabled)(mt32emu_const_context context); + typedef struct { MT32EMU_SERVICE_I_V0 } mt32emu_service_i_v0; @@ -306,6 +312,12 @@ typedef struct { MT32EMU_SERVICE_I_V1 } mt32emu_service_i_v1; +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 +} mt32emu_service_i_v2; + /** * Extensible interface for all the library services. * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. @@ -314,9 +326,11 @@ typedef struct { union mt32emu_service_i { const mt32emu_service_i_v0 *v0; const mt32emu_service_i_v1 *v1; + const mt32emu_service_i_v2 *v2; }; #undef MT32EMU_SERVICE_I_V0 #undef MT32EMU_SERVICE_I_V1 +#undef MT32EMU_SERVICE_I_V2 #endif /* #ifndef MT32EMU_C_TYPES_H */ diff --git a/src/SOUND/munt/c_interface/cpp_interface.h b/src/SOUND/munt/c_interface/cpp_interface.h index f40ed7037..3b02c0325 100644 --- a/src/SOUND/munt/c_interface/cpp_interface.h +++ b/src/SOUND/munt/c_interface/cpp_interface.h @@ -61,6 +61,7 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_flush_midi_queue i.v0->flushMIDIQueue #define mt32emu_set_midi_event_queue_size i.v0->setMIDIEventQueueSize #define mt32emu_set_midi_receiver i.v0->setMIDIReceiver +#define mt32emu_get_internal_rendered_sample_count iV2()->getInternalRenderedSampleCount #define mt32emu_parse_stream i.v0->parseStream #define mt32emu_parse_stream_at i.v0->parseStream_At #define mt32emu_play_short_message i.v0->playShortMessage @@ -90,6 +91,8 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_get_reverb_output_gain i.v0->getReverbOutputGain #define mt32emu_set_reversed_stereo_enabled i.v0->setReversedStereoEnabled #define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled +#define mt32emu_set_nice_amp_ramp_enabled iV2()->setNiceAmpRampEnabled +#define mt32emu_is_nice_amp_ramp_enabled iV2()->isNiceAmpRampEnabled #define mt32emu_render_bit16s i.v0->renderBit16s #define mt32emu_render_float i.v0->renderFloat #define mt32emu_render_bit16s_streams i.v0->renderBit16sStreams @@ -213,6 +216,7 @@ public: void setMIDIReceiver(mt32emu_midi_receiver_i midi_receiver, void *instance_data) { mt32emu_set_midi_receiver(c, midi_receiver, instance_data); } void setMIDIReceiver(IMidiReceiver &midi_receiver) { setMIDIReceiver(CppInterfaceImpl::getMidiReceiverThunk(), &midi_receiver); } + Bit32u getInternalRenderedSampleCount() { return mt32emu_get_internal_rendered_sample_count(c); } void parseStream(const Bit8u *stream, Bit32u length) { mt32emu_parse_stream(c, stream, length); } void parseStream_At(const Bit8u *stream, Bit32u length, Bit32u timestamp) { mt32emu_parse_stream_at(c, stream, length, timestamp); } void playShortMessage(Bit32u message) { mt32emu_play_short_message(c, message); } @@ -249,6 +253,9 @@ public: void setReversedStereoEnabled(const bool enabled) { mt32emu_set_reversed_stereo_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } bool isReversedStereoEnabled() { return mt32emu_is_reversed_stereo_enabled(c) != MT32EMU_BOOL_FALSE; } + void setNiceAmpRampEnabled(const bool enabled) { mt32emu_set_nice_amp_ramp_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } + bool isNiceAmpRampEnabled() { return mt32emu_is_nice_amp_ramp_enabled(c) != MT32EMU_BOOL_FALSE; } + void renderBit16s(Bit16s *stream, Bit32u len) { mt32emu_render_bit16s(c, stream, len); } void renderFloat(float *stream, Bit32u len) { mt32emu_render_float(c, stream, len); } void renderBit16sStreams(const mt32emu_dac_output_bit16s_streams *streams, Bit32u len) { mt32emu_render_bit16s_streams(c, streams, len); } @@ -271,6 +278,7 @@ private: #if MT32EMU_API_TYPE == 2 const mt32emu_service_i_v1 *iV1() { return (getVersionID() < MT32EMU_SERVICE_VERSION_1) ? NULL : i.v1; } + const mt32emu_service_i_v2 *iV2() { return (getVersionID() < MT32EMU_SERVICE_VERSION_2) ? NULL : i.v2; } #endif }; @@ -421,6 +429,7 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_flush_midi_queue #undef mt32emu_set_midi_event_queue_size #undef mt32emu_set_midi_receiver +#undef mt32emu_get_internal_rendered_sample_count #undef mt32emu_parse_stream #undef mt32emu_parse_stream_at #undef mt32emu_play_short_message @@ -450,6 +459,8 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_get_reverb_output_gain #undef mt32emu_set_reversed_stereo_enabled #undef mt32emu_is_reversed_stereo_enabled +#undef mt32emu_set_nice_amp_ramp_enabled +#undef mt32emu_is_nice_amp_ramp_enabled #undef mt32emu_render_bit16s #undef mt32emu_render_float #undef mt32emu_render_bit16s_streams diff --git a/src/SOUND/munt/config.h b/src/SOUND/munt/config.h index 7b6cd736f..9cbdf2bc6 100644 --- a/src/SOUND/munt/config.h +++ b/src/SOUND/munt/config.h @@ -18,9 +18,9 @@ #ifndef MT32EMU_CONFIG_H #define MT32EMU_CONFIG_H -#define MT32EMU_VERSION "2.1.0" +#define MT32EMU_VERSION "2.2.0" #define MT32EMU_VERSION_MAJOR 2 -#define MT32EMU_VERSION_MINOR 1 +#define MT32EMU_VERSION_MINOR 2 #define MT32EMU_VERSION_PATCH 0 /* Library Exports Configuration diff --git a/src/SOUND/munt/globals.h b/src/SOUND/munt/globals.h index d9b4e02c1..2d984c82b 100644 --- a/src/SOUND/munt/globals.h +++ b/src/SOUND/munt/globals.h @@ -87,7 +87,7 @@ #define MT32EMU_MAX_STREAM_BUFFER_SIZE 32768 /* This should correspond to the MIDI buffer size used in real h/w devices. - * CM-32L control ROM seems using 1000 bytes, old MT-32 isn't confirmed by now. + * CM-32L control ROM is using 1000 bytes, and MT-32 GEN0 is using only 240 bytes (semi-confirmed by now). */ #define MT32EMU_SYSEX_BUFFER_SIZE 1000 diff --git a/src/SOUND/munt/srchelper/srctools/include/FloatSampleProvider.h b/src/SOUND/munt/srchelper/srctools/include/FloatSampleProvider.h index e48afcced..9820769f7 100644 --- a/src/SOUND/munt/srchelper/srctools/include/FloatSampleProvider.h +++ b/src/SOUND/munt/srchelper/srctools/include/FloatSampleProvider.h @@ -24,7 +24,7 @@ typedef float FloatSample; /** Interface defines an abstract source of samples. It can either define a single channel stream or a stream with interleaved channels. */ class FloatSampleProvider { public: - virtual ~FloatSampleProvider() {}; + virtual ~FloatSampleProvider() {} virtual void getOutputSamples(FloatSample *outBuffer, unsigned int size) = 0; }; diff --git a/src/SOUND/munt/srchelper/srctools/include/ResamplerStage.h b/src/SOUND/munt/srchelper/srctools/include/ResamplerStage.h index 6aea9624d..e335c0c38 100644 --- a/src/SOUND/munt/srchelper/srctools/include/ResamplerStage.h +++ b/src/SOUND/munt/srchelper/srctools/include/ResamplerStage.h @@ -24,7 +24,7 @@ namespace SRCTools { /** Interface defines an abstract source of samples. It can either define a single channel stream or a stream with interleaved channels. */ class ResamplerStage { public: - virtual ~ResamplerStage() {}; + virtual ~ResamplerStage() {} /** Returns a lower estimation of required number of input samples to produce the specified number of output samples. */ virtual unsigned int estimateInLength(const unsigned int outLength) const = 0; From e7c9e28d1a45f720d6520928531e1074c33846a5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 12 Aug 2017 01:52:52 +0200 Subject: [PATCH 72/82] Fixed more bugs (and a memory leak) regarding status bar pane updates. --- src/WIN/win.c | 81 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/src/WIN/win.c b/src/WIN/win.c index d34465997..1aeaddb6d 100644 --- a/src/WIN/win.c +++ b/src/WIN/win.c @@ -978,9 +978,18 @@ void destroy_menu_handles(void) return; } + if (!sb_menu_handles) + { + return; + } + for (i = 0; i < sb_parts; i++) { - DestroyMenu(sb_menu_handles[i]); + if (sb_menu_handles[i]) + { + DestroyMenu(sb_menu_handles[i]); + sb_menu_handles[i] = NULL; + } } free(sb_menu_handles); @@ -995,12 +1004,22 @@ void destroy_tips(void) return; } + if (!sbTips) + { + return; + } + for (i = 0; i < sb_parts; i++) { - free(sbTips[i]); + if (sbTips[i]) + { + free(sbTips[i]); + sbTips[i] = NULL; + } } free(sbTips); + sbTips = NULL; } void update_status_bar_panes(HWND hwnds) @@ -1031,16 +1050,34 @@ void update_status_bar_panes(HWND hwnds) SendMessage(hwnds, SB_SETICON, i, (LPARAM) NULL); } - sb_parts = 0; + SendMessage(hwnds, SB_SETPARTS, (WPARAM) 0, (LPARAM) NULL); - free(iStatusWidths); - free(sb_part_meanings); - free(sb_part_icons); - free(sb_icon_flags); + if (iStatusWidths) + { + free(iStatusWidths); + iStatusWidths = NULL; + } + if (sb_part_meanings) + { + free(sb_part_meanings); + sb_part_meanings = NULL; + } + if (sb_part_icons) + { + free(sb_part_icons); + sb_part_icons = NULL; + } + if (sb_icon_flags) + { + free(sb_icon_flags); + sb_icon_flags = NULL; + } destroy_menu_handles(); destroy_tips(); } + sb_parts = 0; + for (i = 0; i < FDD_NUM; i++) { if (fdd_get_type(i) != 0) @@ -1051,6 +1088,18 @@ void update_status_bar_panes(HWND hwnds) } for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) && !(models[model].flags & MODEL_HAS_IDE)) + { + continue; + } + if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) && !(models[model].flags & MODEL_HAS_IDE)) + { + continue; + } + if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (scsi_card_current == 0)) + { + continue; + } if (cdrom_drives[i].bus_type != 0) { sb_parts++; @@ -1058,7 +1107,7 @@ void update_status_bar_panes(HWND hwnds) } for (i = 0; i < HDC_NUM; i++) { - if (hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) + if ((hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0)) { sb_parts++; } @@ -1118,6 +1167,18 @@ void update_status_bar_panes(HWND hwnds) } for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) && !(models[model].flags & MODEL_HAS_IDE)) + { + continue; + } + if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) && !(models[model].flags & MODEL_HAS_IDE)) + { + continue; + } + if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (scsi_card_current == 0)) + { + continue; + } if (cdrom_drives[i].bus_type != 0) { edge += SB_ICON_WIDTH; @@ -1128,7 +1189,7 @@ void update_status_bar_panes(HWND hwnds) } for (i = 0; i < HDC_NUM; i++) { - if (hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) + if ((hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0)) { edge += SB_ICON_WIDTH; iStatusWidths[sb_parts] = edge; @@ -1171,7 +1232,7 @@ void update_status_bar_panes(HWND hwnds) sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_IDE_PIO_AND_DMA; sb_parts++; } - if (c_scsi) + if (c_scsi && (scsi_card_current != 0)) { edge += SB_ICON_WIDTH; iStatusWidths[sb_parts] = edge; From 9a86aa0a4bccc262c57d3c49a99511439a22fd3d Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 12 Aug 2017 02:02:49 +0200 Subject: [PATCH 73/82] Applied the Voodoo commits from mainline PCem. --- src/VIDEO/vid_voodoo.c | 2 +- src/VIDEO/vid_voodoo_codegen_x86-64.h | 24 +++++++++++------------ src/VIDEO/vid_voodoo_codegen_x86.h | 28 ++++++++++++--------------- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/VIDEO/vid_voodoo.c b/src/VIDEO/vid_voodoo.c index 042e88a42..3c7db817e 100644 --- a/src/VIDEO/vid_voodoo.c +++ b/src/VIDEO/vid_voodoo.c @@ -6116,7 +6116,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) default: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) { - fatal("Unknown register write in CMDFIFO mode %08x %08x\n", addr, val); + pclog("Unknown register write in CMDFIFO mode %08x %08x\n", addr, val); } else { diff --git a/src/VIDEO/vid_voodoo_codegen_x86-64.h b/src/VIDEO/vid_voodoo_codegen_x86-64.h index 160708b93..bdad42a70 100644 --- a/src/VIDEO/vid_voodoo_codegen_x86-64.h +++ b/src/VIDEO/vid_voodoo_codegen_x86-64.h @@ -800,10 +800,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0x47); addbyte(0xc3); - if (depth_jump_pos) - *(uint8_t *)&code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; - if (depth_jump_pos) - *(uint8_t *)&code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; + if (depth_jump_pos) + *(uint8_t *)&code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; + if (depth_jump_pos) + *(uint8_t *)&code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; if ((params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) { @@ -1047,8 +1047,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[1]); addbyte(0x39); /*CMP EAX, EDX*/ addbyte(0xd0); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); addbyte(0xc2); addbyte(0x66); /*MOVD XMM0, EAX*/ addbyte(0x0f); @@ -1201,8 +1201,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[1]); addbyte(0x39); /*CMP EAX, EDX*/ addbyte(0xd0); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); addbyte(0xc2); break; case TCA_MSELECT_LOD_FRAC: @@ -1371,8 +1371,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[0]); addbyte(0x39); /*CMP EAX, EDX*/ addbyte(0xd0); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); addbyte(0xc2); addbyte(0x66); /*MOVD XMM4, EAX*/ addbyte(0x0f); @@ -1569,8 +1569,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[1]); addbyte(0x39); /*CMP EBX, EDX*/ addbyte(0xd3); - addbyte(0x0f); /*CMOVA EBX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EBX, EDX*/ + addbyte(0x4d); addbyte(0xda); break; case TCA_MSELECT_LOD_FRAC: diff --git a/src/VIDEO/vid_voodoo_codegen_x86.h b/src/VIDEO/vid_voodoo_codegen_x86.h index 0cd0fc7eb..668d64a67 100644 --- a/src/VIDEO/vid_voodoo_codegen_x86.h +++ b/src/VIDEO/vid_voodoo_codegen_x86.h @@ -759,14 +759,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0x47); addbyte(0xc3); - if (depth_jump_pos) - { - *(uint8_t *)&code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; - } - if (depth_jump_pos2) - { - *(uint8_t *)&code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; - } + if (depth_jump_pos) + *(uint8_t *)&code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; + if (depth_jump_pos) + *(uint8_t *)&code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; if ((params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) { @@ -1034,8 +1030,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[1]); addbyte(0x39); /*CMP EAX, EDX*/ addbyte(0xd0); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); addbyte(0xc2); addbyte(0x66); /*MOVD XMM0, EAX*/ addbyte(0x0f); @@ -1186,8 +1182,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[1]); addbyte(0x39); /*CMP EAX, EDX*/ addbyte(0xd0); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); addbyte(0xc2); break; case TCA_MSELECT_LOD_FRAC: @@ -1356,8 +1352,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[0]); addbyte(0x39); /*CMP EAX, EDX*/ addbyte(0xd0); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); addbyte(0xc2); addbyte(0x66); /*MOVD XMM4, EAX*/ addbyte(0x0f); @@ -1552,8 +1548,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(params->detail_scale[1]); addbyte(0x39); /*CMP EBX, EDX*/ addbyte(0xd3); - addbyte(0x0f); /*CMOVA EBX, EDX*/ - addbyte(0x47); + addbyte(0x0f); /*CMOVNL EBX, EDX*/ + addbyte(0x4d); addbyte(0xda); break; case TCA_MSELECT_LOD_FRAC: From 3b6677660198bec4e389dad17a101972db248173 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 14 Aug 2017 19:43:08 +0200 Subject: [PATCH 74/82] Improved memory configuration setting accuracy when 1MB memory installed (mainline PCem patch from Greatpsycho); MovQ MMX Realmode bugfix (mainline PCem patch from JosepMa); Tweaked the buffer for MT-32 and FluidSynth so they sound better (patch from bit). --- src/CPU/x86_ops_mmx_mov.h | 2 +- src/SOUND/midi_fluidsynth.c | 45 +++++++++++-- src/SOUND/midi_mt32.c | 42 +++++++++---- src/mem.c | 2 +- src/mem.h | 1 + src/scat.c | 122 +++++++++++------------------------- 6 files changed, 112 insertions(+), 102 deletions(-) diff --git a/src/CPU/x86_ops_mmx_mov.h b/src/CPU/x86_ops_mmx_mov.h index 8cc0c8e26..d96df747b 100644 --- a/src/CPU/x86_ops_mmx_mov.h +++ b/src/CPU/x86_ops_mmx_mov.h @@ -136,7 +136,7 @@ static int opMOVQ_mm_q_a16(uint32_t fetchdat) else { CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); - writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1; + writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); if (cpu_state.abrt) return 1; CLOCK_CYCLES(2); } return 0; diff --git a/src/SOUND/midi_fluidsynth.c b/src/SOUND/midi_fluidsynth.c index 453997065..7f4122d68 100644 --- a/src/SOUND/midi_fluidsynth.c +++ b/src/SOUND/midi_fluidsynth.c @@ -15,7 +15,8 @@ #include "midi.h" #include "sound.h" -#define RENDER_RATE 30 +#define RENDER_RATE 100 +#define BUFFER_SEGMENTS 10 extern void givealbuffer_midi(void *buf, uint32_t size); extern void pclog(const char *format, ...); @@ -111,9 +112,41 @@ void fluidsynth_poll(void) static void fluidsynth_thread(void *param) { fluidsynth_t* data = (fluidsynth_t*)param; + int buf_pos = 0; + int buf_size = data->buf_size / BUFFER_SEGMENTS; while (1) { thread_wait_event(data->event, -1); + if (sound_is_float) + { + float *buf = (float*)((uint8_t*)data->buffer + buf_pos); + memset(buf, 0, buf_size); + if (data->synth) + f_fluid_synth_write_float(data->synth, buf_size/(2 * sizeof(float)), buf, 0, 2, buf, 1, 2); + buf_pos += buf_size; + if (buf_pos >= data->buf_size) + { + if (soundon) + givealbuffer_midi(data->buffer, data->buf_size / sizeof(float)); + buf_pos = 0; + } + } + else + { + int16_t *buf = (int16_t*)((uint8_t*)data->buffer_int16 + buf_pos); + memset(buf, 0, buf_size); + if (data->synth) + f_fluid_synth_write_s16(data->synth, buf_size/(2 * sizeof(int16_t)), buf, 0, 2, buf, 1, 2); + buf_pos += buf_size; + if (buf_pos >= data->buf_size) + { + if (soundon) + givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); + buf_pos = 0; + } + } + +#if 0 if (sound_is_float) { memset(data->buffer, 0, data->buf_size * sizeof(float)); @@ -130,6 +163,7 @@ static void fluidsynth_thread(void *param) if (soundon) givealbuffer_midi(data->buffer_int16, data->buf_size); } +#endif } } @@ -253,16 +287,17 @@ void* fluidsynth_init(void) double samplerate; f_fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); data->samplerate = (int)samplerate; - data->buf_size = data->samplerate/RENDER_RATE*2; if (sound_is_float) { - data->buffer = malloc(data->buf_size * sizeof(float)); + data->buf_size = (data->samplerate/RENDER_RATE)*2*sizeof(float)*BUFFER_SEGMENTS; + data->buffer = malloc(data->buf_size); data->buffer_int16 = NULL; } else { + data->buf_size = (data->samplerate/RENDER_RATE)*2*sizeof(int16_t)*BUFFER_SEGMENTS; data->buffer = NULL; - data->buffer_int16 = malloc(data->buf_size * sizeof(int16_t)); + data->buffer_int16 = malloc(data->buf_size); } data->event = thread_create_event(); data->thread_h = thread_create(fluidsynth_thread, data); @@ -299,11 +334,13 @@ void fluidsynth_close(void* p) if (data->buffer) { free(data->buffer); + data->buffer = NULL; } if (data->buffer_int16) { free(data->buffer_int16); + data->buffer_int16 = NULL; } /* Unload the DLL if possible. */ diff --git a/src/SOUND/midi_mt32.c b/src/SOUND/midi_mt32.c index ddf561ee0..2e81c6265 100644 --- a/src/SOUND/midi_mt32.c +++ b/src/SOUND/midi_mt32.c @@ -83,7 +83,8 @@ int cm32l_available() static thread_t *thread_h = NULL; static event_t *event = NULL; -#define RENDER_RATE 30 +#define RENDER_RATE 100 +#define BUFFER_SEGMENTS 10 static uint32_t samplerate = 44100; static int buf_size = 0; @@ -115,22 +116,37 @@ extern int soundon; static void mt32_thread(void *param) { + int buf_pos = 0; + int bsize = buf_size / BUFFER_SEGMENTS; while (1) { thread_wait_event(event, -1); + if (sound_is_float) { - memset(buffer, 0, buf_size * sizeof(float)); - mt32_stream(buffer, (samplerate/RENDER_RATE)); - if (soundon) - givealbuffer_midi(buffer, buf_size); + float *buf = (float *) ((uint8_t*)buffer + buf_pos); + memset(buf, 0, bsize); + mt32_stream(buf, bsize / (2 * sizeof(float))); + buf_pos += bsize; + if (buf_pos >= buf_size) + { + if (soundon) + givealbuffer_midi(buffer, buf_size / sizeof(float)); + buf_pos = 0; + } } else { - memset(buffer_int16, 0, buf_size * sizeof(int16_t)); - mt32_stream_int16(buffer_int16, (samplerate/RENDER_RATE)); - if (soundon) - givealbuffer_midi(buffer_int16, buf_size); + int16_t *buf = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos); + memset(buf, 0, bsize); + mt32_stream_int16(buf, bsize / (2 * sizeof(int16_t))); + buf_pos += bsize; + if (buf_pos >= buf_size) + { + if (soundon) + givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t)); + buf_pos = 0; + } } } } @@ -162,16 +178,18 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) event = thread_create_event(); thread_h = thread_create(mt32_thread, 0); samplerate = mt32emu_get_actual_stereo_output_samplerate(context); - buf_size = samplerate/RENDER_RATE*2; + /* buf_size = samplerate/RENDER_RATE*2; */ if (sound_is_float) { - buffer = malloc(buf_size * sizeof(float)); + buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(float); + buffer = malloc(buf_size); buffer_int16 = NULL; } else { + buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(int16_t); buffer = NULL; - buffer_int16 = malloc(buf_size * sizeof(int16_t)); + buffer_int16 = malloc(buf_size); } mt32emu_set_output_gain(context, device_get_config_int("output_gain")/100.0f); diff --git a/src/mem.c b/src/mem.c index 5ab4e5899..0fe8a0dd7 100644 --- a/src/mem.c +++ b/src/mem.c @@ -40,7 +40,7 @@ static int _mem_state[0x40000]; static mem_mapping_t base_mapping; mem_mapping_t ram_low_mapping; mem_mapping_t ram_high_mapping; -static mem_mapping_t ram_mid_mapping; +mem_mapping_t ram_mid_mapping; static mem_mapping_t ram_remapped_mapping; mem_mapping_t bios_mapping[8]; mem_mapping_t bios_high_mapping[8]; diff --git a/src/mem.h b/src/mem.h index 651095b6b..ec9c44740 100644 --- a/src/mem.h +++ b/src/mem.h @@ -176,6 +176,7 @@ void mem_flush_write_page(uint32_t addr, uint32_t virt); void mem_reset_page_blocks(); extern mem_mapping_t ram_low_mapping; +extern mem_mapping_t ram_mid_mapping; void mem_remap_top_256k(); void mem_remap_top_384k(); diff --git a/src/scat.c b/src/scat.c index 77dd8f308..5758cd4b9 100644 --- a/src/scat.c +++ b/src/scat.c @@ -27,6 +27,7 @@ void scat_shadow_state_update() { int i, val; + /* TODO - ROMCS enable features should be implemented later. */ for (i = 0; i < 24; i++) { val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL; @@ -95,7 +96,7 @@ void scat_set_xms_bound(uint8_t val) break; } - if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) + if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) { if (val != 1) { @@ -133,8 +134,12 @@ uint32_t get_scat_addr(uint32_t addr, scat_t *p) } else if (p == NULL && mem_size < 2048 && ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 7)) addr &= 0x7FFFF; - if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && addr >= 0x100000) - addr -= 0x60000; + + if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) + { + if(addr >= 0x100000) addr -= 0x60000; + else if(addr >= 0xA0000) addr = 0xFFFFFFFF; + } return addr; } @@ -153,8 +158,9 @@ void scat_set_global_EMS_state(int state) { virt_addr = get_scat_addr(base_addr, &scat_stat[i]); if(i < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[i]); - mem_mapping_set_exec(&scat_mapping[i], ram + virt_addr); mem_mapping_enable(&scat_mapping[i]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[i], ram + virt_addr); + else mem_mapping_set_exec(&scat_mapping[i], NULL); } else { @@ -214,11 +220,18 @@ void scat_write(uint16_t port, uint8_t val, void *priv) { if((val & 0x0F) == 3) { + if(mem_size > 640) mem_mapping_disable(&scat_A000_BFFF_mapping); + if(mem_size > 768) mem_mapping_disable(&ram_mid_mapping); mem_mapping_enable(&scat_shadowram_mapping); } else { mem_mapping_disable(&scat_shadowram_mapping); + if(mem_size > 640 && (val & 0x0F) > 3) + { + mem_mapping_enable(&scat_A000_BFFF_mapping); + if(mem_size > 768) mem_mapping_enable(&ram_mid_mapping); + } } if(mem_size < 2048) { @@ -252,6 +265,9 @@ void scat_write(uint16_t port, uint8_t val, void *priv) } if (scat_reg_valid) scat_regs[scat_index] = val; +#ifndef RELEASE_BUILD + else pclog("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc); +#endif if (scat_shadow_update) scat_shadow_state_update(); break; @@ -271,19 +287,27 @@ void scat_write(uint16_t port, uint8_t val, void *priv) break; case 0x208: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x40) + case 0x218: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { index = scat_ems_reg_2xA & 0x1F; scat_stat[index].regs_2x8 = val; + base_addr = (index + 16) << 14; + if(index >= 24) + base_addr += 0x30000; if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80)) { + virt_addr = get_scat_addr(base_addr, &scat_stat[index]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); + else mem_mapping_set_exec(&scat_mapping[index], NULL); flushmmucache(); } } break; case 0x209: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x40) + case 0x219: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { index = scat_ems_reg_2xA & 0x1F; scat_stat[index].regs_2x9 = val; @@ -297,7 +321,8 @@ void scat_write(uint16_t port, uint8_t val, void *priv) { virt_addr = get_scat_addr(base_addr, &scat_stat[index]); if(index < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[index]); - mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); + else mem_mapping_set_exec(&scat_mapping[index], NULL); mem_mapping_enable(&scat_mapping[index]); } else @@ -316,61 +341,8 @@ void scat_write(uint16_t port, uint8_t val, void *priv) } break; case 0x20A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x40) - { - scat_ems_reg_2xA = val; - } - break; - - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x41) - { - index = scat_ems_reg_2xA & 0x1F; - scat_stat[index].regs_2x8 = val; - - if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80)) - { - flushmmucache(); - } - } - break; - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x41) - { - index = scat_ems_reg_2xA & 0x1F; - scat_stat[index].regs_2x9 = val; - base_addr = (index + 16) << 14; - if (index >= 24) - base_addr += 0x30000; - - if (scat_regs[SCAT_EMS_CONTROL] & 0x80) - { - if (val & 0x80) - { - virt_addr = get_scat_addr(base_addr, &scat_stat[index]); - if(index < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[index]); - mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); - mem_mapping_enable(&scat_mapping[index]); - pclog("Map page %d(address %05X) to address %06X\n", scat_ems_reg_2xA & 0x1f, base_addr, virt_addr); - } - else - { - mem_mapping_set_exec(&scat_mapping[index], ram + base_addr); - mem_mapping_disable(&scat_mapping[index]); - if(index < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[index]); - pclog("Unmap page %d(address %05X)\n", scat_ems_reg_2xA & 0x1f, base_addr); - } - flushmmucache(); - } - - if (scat_ems_reg_2xA & 0x80) - { - scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & 0x1f); - } - } - break; case 0x21A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x41) + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { scat_ems_reg_2xA = val; } @@ -403,42 +375,24 @@ uint8_t scat_read(uint16_t port, void *priv) break; case 0x208: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x40) + case 0x218: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { index = scat_ems_reg_2xA & 0x1F; val = scat_stat[index].regs_2x8; } break; case 0x209: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x40) + case 0x219: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { index = scat_ems_reg_2xA & 0x1F; val = scat_stat[index].regs_2x9; } break; case 0x20A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x40) - { - val = scat_ems_reg_2xA; - } - break; - - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x41) - { - index = scat_ems_reg_2xA & 0x1F; - val = scat_stat[index].regs_2x8; - } - break; - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x41) - { - index = scat_ems_reg_2xA & 0x1F; - val = scat_stat[index].regs_2x9; - } - break; case 0x21A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == 0x41) + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { val = scat_ems_reg_2xA; } From c5da4c74e9076082a33ec7bebd86c501bd5d92af Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 15 Aug 2017 19:49:25 +0200 Subject: [PATCH 75/82] Added BusLogic BT-542B BIOS support (patch from TheCollector1995); Brought the Adaptec AHA-1540B BIOS support to an essentially work state; Fixed some warnings in CPU/808x.c. --- src/CPU/808x.c | 27 +- src/cdrom.h | 1 + src/scsi.h | 17 + src/scsi_aha154x.c | 71 +-- src/scsi_buslogic.c | 1209 ++++++++++++++++++++++++++++++++++++++----- src/scsi_disk.c | 19 +- src/scsi_disk.h | 2 + 7 files changed, 1190 insertions(+), 156 deletions(-) diff --git a/src/CPU/808x.c b/src/CPU/808x.c index dcc95132f..6ff59cbd3 100644 --- a/src/CPU/808x.c +++ b/src/CPU/808x.c @@ -983,7 +983,7 @@ void execx86(int cycs) int8_t offset; int tempws; uint32_t templ; - int c; + unsigned int c; int tempi; int trap; @@ -2439,6 +2439,12 @@ void execx86(int cycs) switch (rmdat&0x38) { case 0x00: /*ROL b,CL*/ + temp2=(temp&0x80)?1:0; + if (!c) + { + cycles-=((cpu_mod==3)?8:28); + break; + } while (c>0) { temp2=(temp&0x80)?1:0; @@ -2454,6 +2460,12 @@ void execx86(int cycs) cycles-=((cpu_mod==3)?8:28); break; case 0x08: /*ROR b,CL*/ + temp2=temp&1; + if (!c) + { + cycles-=((cpu_mod==3)?8:28); + break; + } while (c>0) { temp2=temp&1; @@ -2564,6 +2576,12 @@ void execx86(int cycs) cycles-=((cpu_mod==3)?8:28); break; case 0x08: /*ROR w,CL*/ + tempw2=(tempw&1)?0x8000:0; + if (!c) + { + cycles-=((cpu_mod==3)?8:28); + break; + } while (c>0) { tempw2=(tempw&1)?0x8000:0; @@ -2596,6 +2614,13 @@ void execx86(int cycs) cycles-=((cpu_mod==3)?8:28); break; case 0x18: /*RCR w,CL*/ + templ=flags&C_FLAG; + tempw2=(templ&1)?0x8000:0; + if (!c) + { + cycles-=((cpu_mod==3)?8:28); + break; + } while (c>0) { templ=flags&C_FLAG; diff --git a/src/cdrom.h b/src/cdrom.h index 5b7cb1f8b..17f7f0570 100644 --- a/src/cdrom.h +++ b/src/cdrom.h @@ -233,6 +233,7 @@ void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); void cdrom_insert(uint8_t id); int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); +int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); #define cdrom_sense_error cdrom[id].sense[0] #define cdrom_sense_key cdrom[id].sense[2] diff --git a/src/scsi.h b/src/scsi.h index 68200572b..96d0dc8c7 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -289,6 +289,23 @@ typedef struct { #define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) #define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) +#pragma pack(push,1) +typedef struct +{ + uint8_t command; + unsigned char id:3; + unsigned char reserved:2; + unsigned char lun:3; + uint16_t cylinder; + uint8_t head; + uint8_t sector; + uint8_t secount; + addr24 dma_address; +} BIOSCMD; +#pragma pack(pop) + +uint8_t HACommand03Handler(uint8_t last_id, BIOSCMD *BiosCmd); + /* * diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index 1111f86a3..cbb5554b5 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -12,7 +12,7 @@ * * NOTE: THIS IS CURRENTLY A MESS, but will be cleaned up as I go. * - * Version: @(#)scsi_aha154x.c 1.0.7 2017/06/14 + * Version: @(#)scsi_aha154x.c 1.0.8 2017/08/15 * * Authors: Fred N. van Kempen, * Original Buslogic version by SA1988 and Miran Grca. @@ -182,6 +182,7 @@ static uint16_t aha_ports[] = { 0x0130, 0x0134, 0x0000, 0x0000 }; +#define WALTJE 1 #ifdef WALTJE int aha_do_log = 1; @@ -310,7 +311,8 @@ aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha, int irq, int dma, /* bios_path = ROMFILE; */ if (chip == CHIP_AHA154XB) { - bios_path = L"roms/scsi/adaptec/aha1540b310.bin"; + /* bios_path = L"roms/scsi/adaptec/aha1540b310.bin"; */ + bios_path = L"roms/scsi/adaptec/B_AC00.BIN"; } else { @@ -545,7 +547,7 @@ aha154x_memory(uint8_t cmd) } -#define AHA_RESET_DURATION_NS UINT64_C(50000000) +#define AHA_RESET_DURATION_NS UINT64_C(25000000) /* @@ -1338,6 +1340,7 @@ aha_read(uint16_t port, void *priv) switch (port & 3) { case 0: + default: ret = dev->Status; break; @@ -1386,14 +1389,18 @@ aha_write(uint16_t port, uint8_t val, void *priv) aha_t *dev = (aha_t *)priv; uint8_t Offset; MailboxInit_t *MailboxInit; + BIOSCMD *BiosCmd; ReplyInquireSetupInformation *ReplyISI; + uint16_t cyl = 0; + uint8_t temp = 0; pclog("AHA154X: Write Port 0x%02X, Value %02X\n", port, val); switch (port & 3) { case 0: if ((val & CTRL_HRST) || (val & CTRL_SRST)) { - uint8_t Reset = !(val & CTRL_HRST); + uint8_t Reset = (val & CTRL_HRST); + pclog("Reset completed = %x\n", Reset); aha_reset_ctrl(dev, Reset); break; } @@ -1466,10 +1473,7 @@ aha_write(uint16_t port, uint8_t val, void *priv) break; case 0x29: - if (dev->chip != CHIP_AHA154XB) - { - dev->CmdParamLeft = 2; - } + dev->CmdParamLeft = 2; break; case 0x91: @@ -1511,7 +1515,16 @@ aha_0x01: break; case 0x03: - dev->DataBuf[0] = 0x00; + BiosCmd = (BIOSCMD *)dev->CmdBuf; + + cyl = ((BiosCmd->cylinder & 0xff) << 8) | ((BiosCmd->cylinder >> 8) & 0xff); + BiosCmd->cylinder = cyl; + temp = BiosCmd->id; + BiosCmd->id = BiosCmd->lun; + BiosCmd->lun = temp; + pclog("C: %04X, H: %02X, S: %02X\n", BiosCmd->cylinder, BiosCmd->head, BiosCmd->sector); + dev->DataBuf[0] = HACommand03Handler(7, BiosCmd); + pclog("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); dev->DataReplyLeft = 1; break; @@ -1683,32 +1696,17 @@ aha_0x01: break; case 0x28: - if (dev->chip == CHIP_AHA154XB) - { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - else - { - dev->DataBuf[0] = 0x08; - dev->DataBuf[1] = dev->Lock; - dev->DataReplyLeft = 2; - } + dev->DataBuf[0] = 0x08; + dev->DataBuf[1] = dev->Lock; + dev->DataReplyLeft = 2; break; case 0x29: dev->DataReplyLeft = 0; - if (dev->chip == CHIP_AHA154XB) - { - dev->Status |= STAT_INVCMD; - } - else - { - if (dev->CmdBuf[1] == dev->Lock) { - if (dev->CmdBuf[0] & 1) { - dev->Lock = 1; - } else { - dev->Lock = 0; - } + if (dev->CmdBuf[1] == dev->Lock) { + if (dev->CmdBuf[0] & 1) { + dev->Lock = 1; + } else { + dev->Lock = 0; } } break; @@ -2316,7 +2314,14 @@ aha_init(int chip, int has_bios) if (bios) { /* Perform AHA-154xNN-specific initialization. */ - aha154x_bios(dev->Base, bios_addr, &dev->aha, dev->Irq, dev->DmaChannel, chip); + if (chip == CHIP_AHA154XB) + { + rom_init(&dev->bios, L"roms/scsi/adaptec/B_AC00.BIN", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + } + else + { + aha154x_bios(dev->Base, bios_addr, &dev->aha, dev->Irq, dev->DmaChannel, chip); + } } return(dev); diff --git a/src/scsi_buslogic.c b/src/scsi_buslogic.c index 94348fe76..25ad0e928 100644 --- a/src/scsi_buslogic.c +++ b/src/scsi_buslogic.c @@ -10,7 +10,7 @@ * 0 - BT-542B ISA; * 1 - BT-958 PCI (but BT-542B ISA on non-PCI machines) * - * Version: @(#)scsi_buslogic.c 1.0.4 2017/06/14 + * Version: @(#)scsi_buslogic.c 1.0.5 2017/08/15 * * Authors: TheCollector1995, * Miran Grca, @@ -39,7 +39,7 @@ #include "scsi_buslogic.h" -#define BUSLOGIC_RESET_DURATION_NS UINT64_C(50000000) +#define BUSLOGIC_RESET_DURATION_NS UINT64_C(250000) /* @@ -437,6 +437,29 @@ typedef union { } CCBU; #pragma pack(pop) +#pragma pack(push,1) +typedef struct +{ + /** Data length. */ + uint32_t DataLength; + /** Data pointer. */ + uint32_t DataPointer; + /** The device the request is sent to. */ + uint8_t TargetId; + /** The LUN in the device. */ + uint8_t LogicalUnit; + /** Reserved */ + unsigned char Reserved1 : 3; + /** Data direction for the request. */ + unsigned char DataDirection : 2; + /** Reserved */ + unsigned char Reserved2 : 3; + /** Length of the SCSI CDB. */ + uint8_t CDBLength; + /** The SCSI CDB. (A CDB can be 12 bytes long.) */ + uint8_t CDB[12]; +} ESCMD; +#pragma pack(pop) #pragma pack(push,1) typedef struct { @@ -465,10 +488,10 @@ typedef struct { uint8_t Geometry; uint8_t Control; uint8_t Command; - uint8_t CmdBuf[53]; + uint8_t CmdBuf[128]; uint8_t CmdParam; uint8_t CmdParamLeft; - uint8_t DataBuf[64]; + uint8_t DataBuf[128]; uint16_t DataReply; uint16_t DataReplyLeft; uint32_t MailboxCount; @@ -490,6 +513,7 @@ typedef struct { mem_mapping_t mmio_mapping; int chip; int Card; + int has_bios; } Buslogic_t; #pragma pack(pop) @@ -505,10 +529,9 @@ enum { CHIP_BUSLOGIC_PCI }; - +/* #define ENABLE_BUSLOGIC_LOG 0 */ int buslogic_do_log = 0; - static void BuslogicLog(const char *format, ...) { @@ -525,6 +548,18 @@ BuslogicLog(const char *format, ...) } #define pclog BuslogicLog +static void +SpecificLog(const char *format, ...) +{ +#ifdef ENABLE_BUSLOGIC_LOG + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); +#endif +} static void BuslogicInterrupt(Buslogic_t *bl, int set) @@ -545,10 +580,12 @@ BuslogicInterrupt(Buslogic_t *bl, int set) if (set) { picint(1 << bl->Irq); + //pclog("Interrupt Set\n"); } else { picintc(1 << bl->Irq); + //pclog("Interrupt Cleared\n"); } } } @@ -557,13 +594,13 @@ BuslogicInterrupt(Buslogic_t *bl, int set) static void BuslogicClearInterrupt(Buslogic_t *bl) { - pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); + //pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); bl->Interrupt = 0; - pclog("Lowering IRQ %i\n", bl->Irq); + //pclog("Lowering IRQ %i\n", bl->Irq); BuslogicInterrupt(bl, 0); if (bl->PendingInterrupt) { bl->Interrupt = bl->PendingInterrupt; - pclog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", bl->Interrupt); + //pclog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", bl->Interrupt); if (bl->MailboxOutInterrupts || !(bl->Interrupt & INTR_MBOA)) { if (bl->IrqEnabled) BuslogicInterrupt(bl, 1); } @@ -571,39 +608,14 @@ BuslogicClearInterrupt(Buslogic_t *bl) } } - -static void -BuslogicLocalRAM(Buslogic_t *bl) -{ - /* - * These values are mostly from what I think is right - * looking at the dmesg output from a Linux guest inside - * a VMware server VM. - * - * So they don't have to be right :) - */ - memset(bl->LocalRAM.u8View, 0, sizeof(HALocalRAM)); - bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; - bl->LocalRAM.structured.autoSCSIData.fParityCheckingEnabled = 1; - bl->LocalRAM.structured.autoSCSIData.fExtendedTranslation = 1; /* Same as in geometry register. */ - bl->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = UINT16_MAX; /* All enabled. Maybe mask out non present devices? */ - bl->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = UINT16_MAX; - bl->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = UINT16_MAX; - bl->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = UINT16_MAX; - bl->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = UINT16_MAX; - bl->LocalRAM.structured.autoSCSIData.fStrictRoundRobinMode = bl->StrictRoundRobinMode; - bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = UINT16_MAX; - /** @todo calculate checksum? */ -} - - static void BuslogicReset(Buslogic_t *bl) { + //pclog("BuslogicReset()\n"); BuslogicCallback = 0; BuslogicResetCallback = 0; + bl->Geometry = 0x80; bl->Status = STAT_IDLE | STAT_INIT; - bl->Geometry = 0x80; bl->Command = 0xFF; bl->CmdParam = 0; bl->CmdParamLeft = 0; @@ -617,15 +629,14 @@ BuslogicReset(Buslogic_t *bl) bl->Lock = 0; BuslogicInOperation = 0; - BuslogicClearInterrupt(bl); - - BuslogicLocalRAM(bl); + BuslogicClearInterrupt(bl); } static void BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) { + //pclog("BuslogicResetControl()\n"); BuslogicReset(bl); if (Reset) { bl->Status |= STAT_STST; @@ -638,9 +649,10 @@ BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) static void BuslogicCommandComplete(Buslogic_t *bl) { - bl->DataReply = 0; - bl->Status |= STAT_IDLE; - + pclog("BuslogicCommandComplete()\n"); + bl->DataReply = 0; + bl->Status |= STAT_IDLE; + if (bl->Command != 0x02) { bl->Status &= ~STAT_DFULL; bl->Interrupt = (INTR_ANY | INTR_HACC); @@ -650,7 +662,7 @@ BuslogicCommandComplete(Buslogic_t *bl) } bl->Command = 0xFF; - bl->CmdParam = 0; + bl->CmdParam = 0; } @@ -984,6 +996,889 @@ BuslogicDataBufferFree(Req_t *req) } } +static uint8_t +BuslogicConvertSenseLength(uint8_t RequestSenseLength) +{ + pclog("Unconverted Request Sense length %i\n", RequestSenseLength); + + if (RequestSenseLength == 0) + RequestSenseLength = 14; + else if (RequestSenseLength == 1) + RequestSenseLength = 0; + + pclog("Request Sense length %i\n", RequestSenseLength); + + return(RequestSenseLength); +} + + +static void +BuslogicSCSIBIOSDataBufferAllocate(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN) +{ + uint32_t DataPointer, DataLength; + + DataPointer = ESCSICmd->DataPointer; + DataLength = ESCSICmd->DataLength; + + SpecificLog("BIOS Data Buffer write: length %d, pointer 0x%04X\n", + DataLength, DataPointer); + + if (SCSIDevices[TargetID][LUN].CmdBuffer != NULL) + { + free(SCSIDevices[TargetID][LUN].CmdBuffer); + SCSIDevices[TargetID][LUN].CmdBuffer = NULL; + } + + if ((ESCSICmd->DataDirection != 0x03) && DataLength) + { + uint32_t Address = DataPointer; + + SCSIDevices[TargetID][LUN].InitLength = DataLength; + + SCSIDevices[TargetID][LUN].CmdBuffer = (uint8_t *) malloc(DataLength); + memset(SCSIDevices[TargetID][LUN].CmdBuffer, 0, DataLength); + + if (DataLength > 0) { + DMAPageRead(Address, + (char *)SCSIDevices[TargetID][LUN].CmdBuffer, + SCSIDevices[TargetID][LUN].InitLength); + } + } +} + +static void +BuslogicSCSIBIOSDataBufferFree(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN) +{ + uint32_t DataPointer = 0; + uint32_t DataLength = 0; + uint32_t Address; + uint32_t Residual; + + DataPointer = ESCSICmd->DataPointer; + DataLength = ESCSICmd->DataLength; + + if ((DataLength != 0) && (ESCSICmd->CDB[0] == GPCMD_TEST_UNIT_READY)) { + SpecificLog("Data length not 0 with TEST UNIT READY: %i (%i)\n", + DataLength, SCSIDevices[TargetID][LUN].InitLength); + } + + if (ESCSICmd->CDB[0] == GPCMD_TEST_UNIT_READY) { + DataLength = 0; + } + + SpecificLog("BIOS Data Buffer read: length %d, pointer 0x%04X\n", + DataLength, DataPointer); + + /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without + checking its length, so do this procedure for both read/write commands. */ + if ((DataLength > 0) && + ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || + (ESCSICmd->DataDirection == 0x00))) + { + Address = DataPointer; + + SpecificLog("BusLogic BIOS DMA: Writing %i bytes at %08X\n", DataLength, Address); + DMAPageWrite(Address, (char *)SCSIDevices[TargetID][LUN].CmdBuffer, DataLength); + } + + /* Should be 0 when scatter/gather? */ + if (DataLength >= SCSIDevices[TargetID][LUN].InitLength) { + Residual = DataLength; + Residual -= SCSIDevices[TargetID][LUN].InitLength; + } else { + Residual = 0; + } + + ESCSICmd->DataLength = Residual; + SpecificLog("BIOS Residual data length for reading: %d\n", + ESCSICmd->DataLength); + + if (SCSIDevices[TargetID][LUN].CmdBuffer != NULL) + { + free(SCSIDevices[TargetID][LUN].CmdBuffer); + SCSIDevices[TargetID][LUN].CmdBuffer = NULL; + } +} + +static void +BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t DataReply) +{ + ESCMD *ESCSICmd = (ESCMD *)CmdBuf; + uint8_t hdc_id, hd_phase; + uint8_t cdrom_id, cdrom_phase; + uint32_t i; + uint8_t temp_cdb[12]; + uint8_t last_id = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7; + + DataInBuf[0] = DataInBuf[1] = 0; + + if ((ESCSICmd->TargetId > last_id) || (ESCSICmd->LogicalUnit > 7)) { + DataInBuf[2] = CCB_INVALID_CCB; + DataInBuf[3] = SCSI_STATUS_OK; + return; + } + + SpecificLog("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); + + SCSIStatus = SCSI_STATUS_OK; + SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].InitLength = 0; + + BuslogicSCSIBIOSDataBufferAllocate(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + + if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType == SCSI_NONE) { + SpecificLog("SCSI Target ID %i and LUN %i have no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit); + BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + //BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, 0, 0); + DataInBuf[2] = CCB_SELECTION_TIMEOUT; + DataInBuf[3] = SCSI_STATUS_OK; + } else { + SpecificLog("SCSI Target ID %i and LUN %i detected and working\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + + SpecificLog("Transfer Control %02X\n", ESCSICmd->DataDirection); + SpecificLog("CDB Length %i\n", ESCSICmd->CDBLength); + if (ESCSICmd->DataDirection > 0x03) { + SpecificLog("Invalid control byte: %02X\n", + ESCSICmd->DataDirection); + } + } + + if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType == SCSI_DISK) + { + hdc_id = scsi_hard_disks[ESCSICmd->TargetId][ESCSICmd->LogicalUnit]; + + if (hdc_id == 0xff) fatal("SCSI hard disk on %02i:%02i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + + SpecificLog("SCSI HD command being executed on: SCSI ID %i, SCSI LUN %i, HD %i\n", + ESCSICmd->TargetId, ESCSICmd->LogicalUnit, hdc_id); + + SpecificLog("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); + for (i = 1; i < ESCSICmd->CDBLength; i++) { + SpecificLog("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); + } + + memset(temp_cdb, 0, 12); + if (ESCSICmd->CDBLength <= 12) { + memcpy(temp_cdb, ESCSICmd->CDB, + ESCSICmd->CDBLength); + } else { + memcpy(temp_cdb, ESCSICmd->CDB, 12); + } + + /* + * Since that field in the HDC struct is never used when + * the bus type is SCSI, let's use it for this scope. + */ + shdc[hdc_id].request_length = temp_cdb[1]; + + if (ESCSICmd->CDBLength != 12) { + /* + * Make sure the LUN field of the temporary CDB is always 0, + * otherwise Daemon Tools drives will misbehave when a command + * is passed through to them. + */ + temp_cdb[1] &= 0x1f; + } + + /* Finally, execute the SCSI command immediately and get the transfer length. */ + SCSIPhase = SCSI_PHASE_COMMAND; + scsi_hd_command(hdc_id, temp_cdb); + SCSIStatus = scsi_hd_err_stat_to_scsi(hdc_id); + if (SCSIStatus == SCSI_STATUS_OK) { + hd_phase = scsi_hd_phase_to_scsi(hdc_id); + if (hd_phase == 2) { + /* Command completed - call the phase callback to complete the command. */ + scsi_hd_callback(hdc_id); + } else { + /* Command first phase complete - call the callback to execute the second phase. */ + scsi_hd_callback(hdc_id); + SCSIStatus = scsi_hd_err_stat_to_scsi(hdc_id); + /* Command second phase complete - call the callback to complete the command. */ + scsi_hd_callback(hdc_id); + } + } else { + /* Error (Check Condition) - call the phase callback to complete the command. */ + scsi_hd_callback(hdc_id); + } + + pclog("SCSI Status: %s, Sense: %02X, ASC: %02X, ASCQ: %02X\n", (SCSIStatus == SCSI_STATUS_OK) ? "OK" : "CHECK CONDITION", shdc[hdc_id].sense[2], shdc[hdc_id].sense[12], shdc[hdc_id].sense[13]); + + BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + //BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, (SCSIStatus != SCSI_STATUS_OK), 1); + + pclog("BIOS Request complete\n"); + + if (SCSIStatus == SCSI_STATUS_OK) { + DataInBuf[2] = CCB_COMPLETE; + DataInBuf[3] = SCSI_STATUS_OK; + } else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) { + DataInBuf[2] = CCB_COMPLETE; + DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; + } + } + else if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType == SCSI_CDROM) + { + cdrom_id = scsi_cdrom_drives[ESCSICmd->TargetId][ESCSICmd->LogicalUnit]; + + if (cdrom_id == 0xff) fatal("SCSI CD-ROM on %02i:%02i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + + pclog("CD-ROM command being executed on: SCSI ID %i, SCSI LUN %i, CD-ROM %i\n", + ESCSICmd->TargetId, ESCSICmd->LogicalUnit, cdrom_id); + + pclog("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); + for (i = 1; i < ESCSICmd->CDBLength; i++) { + pclog("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); + } + + memset(temp_cdb, 0, cdrom[cdrom_id].cdb_len); + if (ESCSICmd->CDBLength <= cdrom[cdrom_id].cdb_len) { + memcpy(temp_cdb, ESCSICmd->CDB, + ESCSICmd->CDBLength); + } else { + memcpy(temp_cdb, ESCSICmd->CDB, cdrom[cdrom_id].cdb_len); + } + + /* + * Since that field in the CDROM struct is never used when + * the bus type is SCSI, let's use it for this scope. + */ + cdrom[cdrom_id].request_length = temp_cdb[1]; + + if (ESCSICmd->CDBLength != 12) { + /* + * Make sure the LUN field of the temporary CDB is always 0, + * otherwise Daemon Tools drives will misbehave when a command + * is passed through to them. + */ + temp_cdb[1] &= 0x1f; + } + + /* Finally, execute the SCSI command immediately and get the transfer length. */ + SCSIPhase = SCSI_PHASE_COMMAND; + cdrom_command(cdrom_id, temp_cdb); + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(cdrom_id); + if (SCSIStatus == SCSI_STATUS_OK) { + cdrom_phase = cdrom_atapi_phase_to_scsi(cdrom_id); + if (cdrom_phase == 2) { + /* Command completed - call the phase callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } else { + /* Command first phase complete - call the callback to execute the second phase. */ + cdrom_phase_callback(cdrom_id); + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(cdrom_id); + /* Command second phase complete - call the callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } + } else { + /* Error (Check Condition) - call the phase callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } + + pclog("SCSI Status: %s, Sense: %02X, ASC: %02X, ASCQ: %02X\n", (SCSIStatus == SCSI_STATUS_OK) ? "OK" : "CHECK CONDITION", cdrom[cdrom_id].sense[2], cdrom[cdrom_id].sense[12], cdrom[cdrom_id].sense[13]); + + BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + + pclog("Request complete\n"); + + if (SCSIStatus == SCSI_STATUS_OK) { + DataInBuf[2] = CCB_COMPLETE; + DataInBuf[3] = SCSI_STATUS_OK; + } else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) { + DataInBuf[2] = CCB_COMPLETE; + DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; + } + } + + //BuslogicInOperation = (SCSIDevices[Id][Lun].LunType == SCSI_DISK) ? 0x13 : 3; + pclog("SCSI (%i:%i) -> %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType); + + bl->DataReplyLeft = DataReply; +} + +static uint8_t BuslogicCompletionCode(uint8_t *sense) +{ + switch (sense[12]) + { + case 0x00: + return 0x00; + case 0x20: + return 0x01; + case 0x12: + case 0x21: + return 0x02; + case 0x27: + return 0x03; + case 0x14: case 0x16: + return 0x04; + case 0x10: case 0x11: + return 0x10; + case 0x17: case 0x18: + return 0x11; + case 0x01: case 0x03: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: + case 0x1B: case 0x1C: case 0x1D: + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: + case 0x47: case 0x48: case 0x49: + return 0x20; + case 0x15: + case 0x02: + return 0x40; + case 0x04: + case 0x28: case 0x29: case 0x2A: + return 0xAA; + default: + return 0xFF; + } +} + +uint8_t BuslogicBIOSCommand08(uint8_t id, uint8_t *buffer, int lun_type) +{ + uint32_t len = 0; + uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t rcbuf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int ret = 0; + int i = 0; + uint8_t sc = 0; + + if (lun_type == SCSI_CDROM) + { + ret = cdrom_read_capacity(id, cdb, rcbuf, &len); + sc = BuslogicCompletionCode(cdrom[id].sense); + } + else + { + ret = scsi_hd_read_capacity(id, cdb, rcbuf, &len); + sc = BuslogicCompletionCode(shdc[id].sense); + } + + if (ret == 0) + { + return sc; + } + + memset(buffer, 0, 6); + + for (i = 0; i < 4; i++) + { + buffer[i] = rcbuf[i]; + } + + for (i = 4; i < 6; i++) + { + buffer[i] = rcbuf[(i + 2) ^ 1]; + } + + SpecificLog("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + + return 0; +} + +int BuslogicBIOSCommand15(uint8_t id, uint8_t *buffer, int lun_type) +{ + uint32_t len = 0; + uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t rcbuf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int ret = 0; + int i = 0; + uint8_t sc = 0; + + if (lun_type == SCSI_CDROM) + { + ret = cdrom_read_capacity(id, cdb, rcbuf, &len); + sc = BuslogicCompletionCode(cdrom[id].sense); + } + else + { + ret = scsi_hd_read_capacity(id, cdb, rcbuf, &len); + sc = BuslogicCompletionCode(shdc[id].sense); + } + + memset(buffer, 0, 6); + + for (i = 0; i < 4; i++) + { + buffer[i] = (ret == 0) ? 0 : rcbuf[i]; + } + + buffer[4] = (lun_type == SCSI_CDROM) ? 5 : 0; + if (lun_type == SCSI_CDROM) + { + buffer[5] = 0x80; + } + else + { + buffer[5] = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00; + } + + SpecificLog("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + + return sc; +} + +static void BuslogicSCSICDROMPhaseHandler(uint8_t id) +{ + int phase = 0; + + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(id); + if (SCSIStatus == SCSI_STATUS_OK) + { + phase = cdrom_atapi_phase_to_scsi(id); + if (phase == 2) + { + /* Command completed - call the phase callback to complete the command. */ + cdrom_phase_callback(id); + } + else + { + /* Command first phase complete - call the callback to execute the second phase. */ + cdrom_phase_callback(id); + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(id); + /* Command second phase complete - call the callback to complete the command. */ + cdrom_phase_callback(id); + } + } + else + { + /* Error (Check Condition) - call the phase callback to complete the command. */ + cdrom_phase_callback(id); + } +} + +static void BuslogicSCSIDiskPhaseHandler(uint8_t hdc_id) +{ + int phase = 0; + + SCSIStatus = scsi_hd_err_stat_to_scsi(hdc_id); + if (SCSIStatus == SCSI_STATUS_OK) + { + phase = scsi_hd_phase_to_scsi(hdc_id); + if (phase == 2) + { + /* Command completed - call the phase callback to complete the command. */ + scsi_hd_callback(hdc_id); + } + else + { + /* Command first phase complete - call the callback to execute the second phase. */ + scsi_hd_callback(hdc_id); + SCSIStatus = scsi_hd_err_stat_to_scsi(hdc_id); + /* Command second phase complete - call the callback to complete the command. */ + scsi_hd_callback(hdc_id); + } + } + else + { + /* Error (Check Condition) - call the phase callback to complete the command. */ + scsi_hd_callback(hdc_id); + } +} + +static void BuslogicIDCheck(int lun_type, uint8_t cdrom_id, uint8_t hdc_id, BIOSCMD *BiosCmd) +{ + if (lun_type == SCSI_CDROM) + { + if (cdrom_id == 0xff) + { + fatal("BIOS INT13 CD-ROM on %02i:%02i has disappeared\n", BiosCmd->id, BiosCmd->lun); + } + } + else + { + if (hdc_id == 0xff) + { + fatal("BIOS INT13 hard disk on %02i:%02i has disappeared\n", BiosCmd->id, BiosCmd->lun); + } + } +} + +/* This returns the completion code. */ +uint8_t HACommand03Handler(uint8_t last_id, BIOSCMD *BiosCmd) +{ + uint32_t dma_address; + uint8_t cdrom_id, hdc_id; + int lba = (BiosCmd->cylinder << 9) + (BiosCmd->head << 5) + BiosCmd->sector; + int sector_len = BiosCmd->secount; + int block_shift = 9; + int lun_type = SCSI_NONE; + uint8_t ret = 0; + uint8_t cdb[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + SpecificLog("BIOS Command = 0x%02X\n", BiosCmd->command); + + if ((BiosCmd->id > last_id) || (BiosCmd->lun > 7)) { + return 0x80; + } + + lun_type = SCSIDevices[BiosCmd->id][BiosCmd->lun].LunType; + + cdrom_id = scsi_cdrom_drives[BiosCmd->id][BiosCmd->lun]; + hdc_id = scsi_hard_disks[BiosCmd->id][BiosCmd->lun]; + + SCSIDevices[BiosCmd->id][BiosCmd->lun].InitLength = 0; + + if (lun_type == SCSI_NONE) + { + SpecificLog("BIOS Target ID %i and LUN %i have no device attached\n",BiosCmd->id,BiosCmd->lun); + return 0x80; + } + + dma_address = ADDR_TO_U32(BiosCmd->dma_address); + + SpecificLog("BIOS Data Buffer write: length %d, pointer 0x%04X\n", sector_len, dma_address); + + if (SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer != NULL) + { + free(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer); + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = NULL; + } + + switch(BiosCmd->command) + { + case 0x00: /* Reset Disk System, in practice it's a nop */ + return 0; + + break; + + case 0x01: /* Read Status of Last Operation */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + /* Assuming 14 bytes because that's the default length for SCSI sense, and no command-specific + indication is given. */ + SCSIDevices[BiosCmd->id][BiosCmd->lun].InitLength = 14; + + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = (uint8_t *) malloc(14); + memset(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, 0, 14); + + SCSIStatus = BuslogicBIOSCommand08((lun_type == SCSI_CDROM) ? cdrom_id : hdc_id, SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, lun_type) ? SCSI_STATUS_OK : SCSI_STATUS_CHECK_CONDITION; + + if (sector_len > 0) + { + SpecificLog("BusLogic BIOS DMA: Reading 14 bytes at %08X\n", dma_address); + if (lun_type == SCSI_CDROM) + { + DMAPageWrite(dma_address, (char *)cdrom[cdrom_id].sense, 14); + } + else + { + DMAPageWrite(dma_address, (char *)shdc[hdc_id].sense, 14); + } + } + + if (SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer != NULL) + { + free(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer); + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = NULL; + } + + return BuslogicCompletionCode((lun_type == SCSI_CDROM) ? cdrom[cdrom_id].sense : shdc[hdc_id].sense); + + break; + + case 0x02: /* Read Desired Sectors to Memory */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + if (lun_type == SCSI_CDROM) + { + block_shift = 11; + } + + SCSIDevices[BiosCmd->id][BiosCmd->lun].InitLength = sector_len << block_shift; + + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = (uint8_t *) malloc(sector_len << block_shift); + memset(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, 0, sector_len << block_shift); + + cdb[0] = GPCMD_READ_10; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + cdb[7] = (sector_len >> 8) & 0xff; + cdb[8] = sector_len & 0xff; + + if (lun_type == SCSI_CDROM) + { + cdrom[cdrom_id].request_length = (BiosCmd->lun & 7) << 5; + cdrom_command(cdrom_id, cdb); + BuslogicSCSICDROMPhaseHandler(cdrom_id); + } + else + { + shdc[hdc_id].request_length = (BiosCmd->lun & 7) << 5; + scsi_hd_command(hdc_id, cdb); + BuslogicSCSIDiskPhaseHandler(hdc_id); + } + + if (sector_len > 0) + { + SpecificLog("BusLogic BIOS DMA: Reading %i bytes at %08X\n", sector_len << block_shift, dma_address); + DMAPageWrite(dma_address, (char *)SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, sector_len << block_shift); + } + + if (SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer != NULL) + { + free(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer); + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = NULL; + } + + return BuslogicCompletionCode((lun_type == SCSI_CDROM) ? cdrom[cdrom_id].sense : shdc[hdc_id].sense); + + break; + + case 0x03: /* Write Desired Sectors from Memory */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + if (lun_type == SCSI_CDROM) + { + block_shift = 11; + } + + SCSIDevices[BiosCmd->id][BiosCmd->lun].InitLength = sector_len << block_shift; + + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = (uint8_t *) malloc(sector_len << block_shift); + memset(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, 0, sector_len << block_shift); + + if (sector_len > 0) + { + SpecificLog("BusLogic BIOS DMA: Reading %i bytes at %08X\n", sector_len << block_shift, dma_address); + DMAPageRead(dma_address, (char *)SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, sector_len << block_shift); + } + + cdb[0] = GPCMD_WRITE_10; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + cdb[7] = (sector_len >> 8) & 0xff; + cdb[8] = sector_len & 0xff; + + if (lun_type == SCSI_CDROM) + { + cdrom[cdrom_id].request_length = (BiosCmd->lun & 7) << 5; + cdrom_command(cdrom_id, cdb); + BuslogicSCSICDROMPhaseHandler(cdrom_id); + } + else + { + shdc[hdc_id].request_length = (BiosCmd->lun & 7) << 5; + scsi_hd_command(hdc_id, cdb); + BuslogicSCSIDiskPhaseHandler(hdc_id); + } + + if (SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer != NULL) + { + free(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer); + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = NULL; + } + + return BuslogicCompletionCode((lun_type == SCSI_CDROM) ? cdrom[cdrom_id].sense : shdc[hdc_id].sense); + + break; + + case 0x04: /* Verify Desired Sectors */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + if (lun_type == SCSI_CDROM) + { + block_shift = 11; + } + + cdb[0] = GPCMD_VERIFY_10; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + cdb[7] = (sector_len >> 8) & 0xff; + cdb[8] = sector_len & 0xff; + + if (lun_type == SCSI_CDROM) + { + cdrom[cdrom_id].request_length = (BiosCmd->lun & 7) << 5; + cdrom_command(cdrom_id, cdb); + BuslogicSCSICDROMPhaseHandler(cdrom_id); + } + else + { + shdc[hdc_id].request_length = (BiosCmd->lun & 7) << 5; + scsi_hd_command(hdc_id, cdb); + BuslogicSCSIDiskPhaseHandler(hdc_id); + } + + return BuslogicCompletionCode((lun_type == SCSI_CDROM) ? cdrom[cdrom_id].sense : shdc[hdc_id].sense); + + break; + + case 0x05: /* Format Track, invalid since SCSI has no tracks */ + return 1; + + break; + + case 0x06: /* Identify SCSI Devices, in practice it's a nop */ + return 0; + + break; + + case 0x07: /* Format Unit */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + cdb[0] = GPCMD_FORMAT_UNIT; + + if (lun_type == SCSI_CDROM) + { + cdrom[cdrom_id].request_length = (BiosCmd->lun & 7) << 5; + cdrom_command(cdrom_id, cdb); + BuslogicSCSICDROMPhaseHandler(cdrom_id); + } + else + { + shdc[hdc_id].request_length = (BiosCmd->lun & 7) << 5; + scsi_hd_command(hdc_id, cdb); + BuslogicSCSIDiskPhaseHandler(hdc_id); + } + + return BuslogicCompletionCode((lun_type == SCSI_CDROM) ? cdrom[cdrom_id].sense : shdc[hdc_id].sense); + + break; + + case 0x08: /* Read Drive Parameters */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + SCSIDevices[BiosCmd->id][BiosCmd->lun].InitLength = 6; + + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = (uint8_t *) malloc(6); + memset(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, 0, 6); + + ret = BuslogicBIOSCommand08((lun_type == SCSI_CDROM) ? cdrom_id : hdc_id, SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, lun_type); + + SpecificLog("BusLogic BIOS DMA: Reading 6 bytes at %08X\n", dma_address); + DMAPageWrite(dma_address, (char *)SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, 6); + + if (SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer != NULL) + { + free(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer); + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = NULL; + } + + return ret; + + break; + + case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ + return 0; + + break; + + case 0x0C: /* Seek */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + SCSIDevices[BiosCmd->id][BiosCmd->lun].InitLength = sector_len << block_shift; + + cdb[0] = GPCMD_SEEK_10; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + + if (lun_type == SCSI_CDROM) + { + cdrom[cdrom_id].request_length = (BiosCmd->lun & 7) << 5; + cdrom_command(cdrom_id, cdb); + BuslogicSCSICDROMPhaseHandler(cdrom_id); + } + else + { + shdc[hdc_id].request_length = (BiosCmd->lun & 7) << 5; + scsi_hd_command(hdc_id, cdb); + BuslogicSCSIDiskPhaseHandler(hdc_id); + } + + return (SCSIStatus == SCSI_STATUS_OK) ? 1 : 0; + + break; + + case 0x0D: /* Alternate Disk Reset, in practice it's a nop */ + return 0; + + break; + + case 0x10: /* Test Drive Ready */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + cdb[0] = GPCMD_TEST_UNIT_READY; + + if (lun_type == SCSI_CDROM) + { + cdrom[cdrom_id].request_length = (BiosCmd->lun & 7) << 5; + cdrom_command(cdrom_id, cdb); + BuslogicSCSICDROMPhaseHandler(cdrom_id); + } + else + { + shdc[hdc_id].request_length = (BiosCmd->lun & 7) << 5; + scsi_hd_command(hdc_id, cdb); + BuslogicSCSIDiskPhaseHandler(hdc_id); + } + + return BuslogicCompletionCode((lun_type == SCSI_CDROM) ? cdrom[cdrom_id].sense : shdc[hdc_id].sense); + + break; + + case 0x11: /* Recalibrate */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + cdb[0] = GPCMD_REZERO_UNIT; + + if (lun_type == SCSI_CDROM) + { + cdrom[cdrom_id].request_length = (BiosCmd->lun & 7) << 5; + cdrom_command(cdrom_id, cdb); + BuslogicSCSICDROMPhaseHandler(cdrom_id); + } + else + { + shdc[hdc_id].request_length = (BiosCmd->lun & 7) << 5; + scsi_hd_command(hdc_id, cdb); + BuslogicSCSIDiskPhaseHandler(hdc_id); + } + + return BuslogicCompletionCode((lun_type == SCSI_CDROM) ? cdrom[cdrom_id].sense : shdc[hdc_id].sense); + + break; + + case 0x14: /* Controller Diagnostic */ + return 0; + + break; + + case 0x15: /* Read DASD Type */ + BuslogicIDCheck(lun_type, cdrom_id, hdc_id, BiosCmd); + + SCSIDevices[BiosCmd->id][BiosCmd->lun].InitLength = 6; + + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = (uint8_t *) malloc(6); + memset(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, 0, 6); + + ret = BuslogicBIOSCommand15((lun_type == SCSI_CDROM) ? cdrom_id : hdc_id, SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, lun_type); + + SpecificLog("BusLogic BIOS DMA: Reading 6 bytes at %08X\n", dma_address); + DMAPageWrite(dma_address, (char *)SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer, 6); + + if (SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer != NULL) + { + free(SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer); + SCSIDevices[BiosCmd->id][BiosCmd->lun].CmdBuffer = NULL; + } + + return ret; + + break; + + default: + SpecificLog("BusLogic BIOS: Unimplemented command: %02X\n", BiosCmd->command); + return 1; + + break; + } + + pclog("BIOS Request complete\n"); +} static uint8_t BuslogicRead(uint16_t Port, void *p) @@ -993,15 +1888,21 @@ BuslogicRead(uint16_t Port, void *p) switch (Port & 3) { case 0: + default: Temp = bl->Status; break; case 1: - if (bl->UseLocalRAM) + if (bl->UseLocalRAM && (bl->Command == 0x91)) + { Temp = bl->LocalRAM.u8View[bl->DataReply]; + } else + { Temp = bl->DataBuf[bl->DataReply]; - if (bl->DataReplyLeft) { + } + if (bl->DataReplyLeft) + { bl->DataReply++; bl->DataReplyLeft--; if (!bl->DataReplyLeft) { @@ -1052,19 +1953,23 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Buslogic_t *bl = (Buslogic_t *)p; uint8_t Offset; MailboxInit_t *MailboxInit; + BIOSCMD *BiosCmd; ReplyInquireSetupInformation *ReplyISI; MailboxInitExtended_t *MailboxInitE; ReplyInquireExtendedSetupInformation *ReplyIESI; BuslogicPCIInformation_t *ReplyPI; char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */ int cCharsToTransfer; + uint16_t cyl = 0; pclog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); - switch (Port & 3) { + switch (Port & 3) + { case 0: - if ((Val & CTRL_HRST) || (Val & CTRL_SRST)) { - uint8_t Reset = !(Val & CTRL_HRST); + if ((Val & CTRL_HRST) || (Val & CTRL_SRST)) + { + uint8_t Reset = (Val & CTRL_HRST); BuslogicResetControl(bl, Reset); break; } @@ -1092,12 +1997,16 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->CmdParamLeft = 0; bl->Status &= ~(STAT_INVCMD | STAT_IDLE); - pclog("Buslogic: Operation Code 0x%02X\n", Val); + SpecificLog("Buslogic: Operation Code 0x%02X\n", Val); switch (bl->Command) { case 0x01: bl->CmdParamLeft = sizeof(MailboxInit_t); break; - + + case 0x03: + bl->CmdParamLeft = 10; + break; + case 0x25: bl->CmdParamLeft = 1; break; @@ -1108,38 +2017,56 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x09: case 0x0D: case 0x1F: - case 0x21: - case 0x24: bl->CmdParamLeft = 1; + break; + + case 0x21: + bl->CmdParamLeft = 5; break; + case 0x1A: + case 0x1B: + bl->CmdParamLeft = 3; + break; + case 0x06: bl->CmdParamLeft = 4; break; - case 0x1C: - case 0x1D: - bl->CmdParamLeft = 3; - break; - case 0x8B: case 0x8D: case 0x8F: case 0x96: bl->CmdParamLeft = 1; break; - + case 0x81: bl->CmdParamLeft = sizeof(MailboxInitExtended_t); break; + + case 0x83: + bl->CmdParamLeft = 12; + break; case 0x8C: bl->CmdParamLeft = 1; break; + case 0x90: + bl->CmdParamLeft = 2; + break; + case 0x91: bl->CmdParamLeft = 2; break; + + case 0x92: + bl->CmdParamLeft = 1; + break; + + case 0x94: + bl->CmdParamLeft = 3; + break; case 0x95: /* Valid only for PCI */ bl->CmdParamLeft = (bl->chip == CHIP_BUSLOGIC_PCI) ? 1 : 0; @@ -1149,10 +2076,16 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->CmdBuf[bl->CmdParam] = Val; bl->CmdParam++; bl->CmdParamLeft--; + + if ((bl->CmdParam == 2) && (bl->Command == 0x90)) + { + bl->CmdParamLeft = bl->CmdBuf[1]; + } } - if (!bl->CmdParamLeft) { - pclog("Running Operation Code 0x%02X\n", bl->Command); + if (!bl->CmdParamLeft) + { + SpecificLog("Running Operation Code 0x%02X\n", bl->Command); switch (bl->Command) { case 0x00: bl->DataReplyLeft = 0; @@ -1177,15 +2110,22 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) break; case 0x03: - bl->DataBuf[0] = 0x00; + BiosCmd = (BIOSCMD *)bl->CmdBuf; + + cyl = ((BiosCmd->cylinder & 0xff) << 8) | ((BiosCmd->cylinder >> 8) & 0xff); + BiosCmd->cylinder = cyl; + SpecificLog("C: %04X, H: %02X, S: %02X\n", BiosCmd->cylinder, BiosCmd->head, BiosCmd->sector); + bl->DataBuf[0] = HACommand03Handler((bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7, BiosCmd); + SpecificLog("BIOS Completion/Status Code %x\n", bl->DataBuf[0]); bl->DataReplyLeft = 1; break; case 0x04: + pclog("Inquire Board\n"); bl->DataBuf[0] = 0x41; bl->DataBuf[1] = 0x41; - bl->DataBuf[2] = '5'; - bl->DataBuf[3] = '0'; + bl->DataBuf[2] = '2'; + bl->DataBuf[3] = '2'; bl->DataReplyLeft = 4; break; @@ -1198,8 +2138,9 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) } bl->DataReplyLeft = 0; break; - + case 0x06: + pclog("Selection Time-Out\n"); bl->DataReplyLeft = 0; break; @@ -1235,6 +2176,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) break; case 0x0B: + pclog("Inquire Configuration\n"); bl->DataBuf[0] = (1 << bl->DmaChannel); if ((bl->Irq >= 9) && (bl->Irq <= 15)) { @@ -1271,7 +2213,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) } break; - case 0x1C: + case 0x1A: { uint32_t FIFOBuf; addr24 Address; @@ -1281,11 +2223,12 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Address.mid = bl->CmdBuf[1]; Address.lo = bl->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); + pclog("Buslogic LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); DMAPageRead(FIFOBuf, (char *)&bl->LocalRAM.u8View[64], 64); } break; - case 0x1D: + case 0x1B: { uint32_t FIFOBuf; addr24 Address; @@ -1295,7 +2238,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Address.mid = bl->CmdBuf[1]; Address.lo = bl->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); - pclog("Buslogic FIFO: Writing 64 bytes at %08X\n", FIFOBuf); + pclog("Buslogic LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); DMAPageWrite(FIFOBuf, (char *)&bl->LocalRAM.u8View[64], 64); } break; @@ -1319,17 +2262,11 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x23: memset(bl->DataBuf, 0, 8); for (i = 8; i < 16; i++) { -#if 1 /* FIXME: Kotori, check this! */ + /* FIXME: Kotori, check this! */ bl->DataBuf[i-8] = 0; for (j=0; j<8; j++) { if (SCSIDevices[i][j].LunType != SCSI_NONE) bl->DataBuf[i-8] |= (1<DataBuf[i] = 0; - for (i=0; j<8; j++) { - if (SCSIDevices[i][j].LunType != SCSI_NONE) - bl->DataBuf[i] |= (1<DataReplyLeft = 8; @@ -1379,14 +2316,27 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->DataReplyLeft = 0; } break; + + case 0x83: + if (bl->CmdParam == 12) + { + bl->CmdParamLeft = bl->CmdBuf[11]; + pclog("Execute SCSI BIOS Command: %u more bytes follow\n", bl->CmdParamLeft); + } + else + { + pclog("Execute SCSI BIOS Command: received %u bytes\n", bl->CmdBuf[0]); + BuslogicSCSIBIOSRequestSetup(bl, bl->CmdBuf, bl->DataBuf, 4); + } + break; case 0x84: - bl->DataBuf[0] = '7'; + bl->DataBuf[0] = '1'; bl->DataReplyLeft = 1; break; case 0x85: - bl->DataBuf[0] = 'B'; + bl->DataBuf[0] = 'E'; bl->DataReplyLeft = 1; break; @@ -1445,6 +2395,13 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) for (i = 0; i < cCharsToTransfer; i++) bl->DataBuf[i] = aModelName[i]; + + pclog("Model Name\n"); + pclog("Buffer 0: %x\n", bl->DataBuf[0]); + pclog("Buffer 1: %x\n", bl->DataBuf[1]); + pclog("Buffer 2: %x\n", bl->DataBuf[2]); + pclog("Buffer 3: %x\n", bl->DataBuf[3]); + pclog("Buffer 4: %x\n", bl->DataBuf[4]); } break; @@ -1459,7 +2416,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); ReplyIESI->uBusType = (bl->chip == CHIP_BUSLOGIC_PCI) ? 'E' : 'A'; /* ISA style */ - ReplyIESI->uBiosAddress = 0; + ReplyIESI->uBiosAddress = 0xd8; ReplyIESI->u16ScatterGatherLimit = 8192; ReplyIESI->cMailbox = bl->MailboxCount; ReplyIESI->uMailboxAddressBase = bl->MailboxOutAddr; @@ -1468,8 +2425,8 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) ReplyIESI->fHostWideSCSI = 1; ReplyIESI->fHostUltraSCSI = 1; } - memcpy(ReplyIESI->aFirmwareRevision, "07B", sizeof(ReplyIESI->aFirmwareRevision)); - pclog("Return Extended Setup Information: %d\n", bl->CmdBuf[0]); + memcpy(ReplyIESI->aFirmwareRevision, "21E", sizeof(ReplyIESI->aFirmwareRevision)); + SpecificLog("Return Extended Setup Information: %d\n", bl->CmdBuf[0]); break; /* VirtualBox has these two modes implemented in reverse. @@ -1487,14 +2444,30 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->DataReplyLeft = 0; break; + case 0x90: + pclog("Store Local RAM\n"); + + Offset = bl->CmdBuf[0]; + bl->DataReplyLeft = 0; + + for (i = 0; i < bl->CmdBuf[1]; i++) + { + bl->LocalRAM.u8View[Offset + i] = bl->CmdBuf[i + 2]; + } + + bl->UseLocalRAM = 0; + bl->DataReply = Offset; + break; + case 0x91: + pclog("Fetch Local RAM\n"); Offset = bl->CmdBuf[0]; bl->DataReplyLeft = bl->CmdBuf[1]; bl->UseLocalRAM = 1; bl->DataReply = Offset; break; - + case 0x95: if (bl->chip == CHIP_BUSLOGIC_PCI) { if (bl->Base != 0) { @@ -1555,18 +2528,25 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->DataReplyLeft = 0; break; - + default: + SpecificLog("Invalid command %x\n", bl->Command); bl->DataReplyLeft = 0; bl->Status |= STAT_INVCMD; break; } } - + if (bl->DataReplyLeft) + { bl->Status |= STAT_DFULL; + pclog("Data Full\n"); + } else if (!bl->CmdParamLeft) + { BuslogicCommandComplete(bl); + pclog("No Command Parameters Left, completing command\n"); + } break; case 2: @@ -1594,22 +2574,6 @@ BuslogicWriteL(uint16_t Port, uint32_t Val, void *p) } -static uint8_t -BuslogicConvertSenseLength(uint8_t RequestSenseLength) -{ - pclog("Unconverted Request Sense length %i\n", RequestSenseLength); - - if (RequestSenseLength == 0) - RequestSenseLength = 14; - else if (RequestSenseLength == 1) - RequestSenseLength = 0; - - pclog("Request Sense length %i\n", RequestSenseLength); - - return(RequestSenseLength); -} - - static void BuslogicSenseBufferFree(Req_t *req, int Copy, int is_hd) { @@ -1668,12 +2632,12 @@ BuslogicHDCommand(Buslogic_t *bl) if (hdc_id == 0xff) fatal("SCSI hard disk on %02i:%02i has disappeared\n", Id, Lun); - pclog("SCSI HD command being executed on: SCSI ID %i, SCSI LUN %i, HD %i\n", + SpecificLog("SCSI HD command being executed on: SCSI ID %i, SCSI LUN %i, HD %i\n", Id, Lun, hdc_id); - pclog("SCSI Cdb[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); + SpecificLog("SCSI Cdb[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); for (i = 1; i < req->CmdBlock.common.CdbLength; i++) { - pclog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); + SpecificLog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); } memset(temp_cdb, 0, 12); @@ -2204,8 +3168,8 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) bl->MMIOBase, 0x20); } } - return; - + return; + case 0x3C: buslogic_pci_regs[addr] = val; if (val != 0xFF) { @@ -2247,7 +3211,9 @@ BuslogicInit(int chip) bl->MMIOBase = 0; bl->Irq = device_get_config_int("irq"); bl->DmaChannel = device_get_config_int("dma"); + bl->has_bios = device_get_config_int("bios"); + if (bl->Base != 0) { if (bl->chip == CHIP_BUSLOGIC_PCI) { io_sethandler(bl->Base, 4, @@ -2261,23 +3227,31 @@ BuslogicInit(int chip) } } + if (bl->has_bios && bl->chip == CHIP_BUSLOGIC_ISA) + { + rom_init(&bl->bios, L"roms/scsi/buslogic/542_470.ROM", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + } + pclog("Building SCSI hard disk map...\n"); build_scsi_hd_map(); pclog("Building SCSI CD-ROM map...\n"); build_scsi_cdrom_map(); - - for (i=0; i<16; i++) { - for (j=0; j<8; j++) { - if (scsi_hard_disks[i][j] != 0xff) { - SCSIDevices[i][j].LunType = SCSI_DISK; + + for (i=0; i<16; i++) + { + for (j=0; j<8; j++) + { + if (scsi_hard_disks[i][j] != 0xff) { + SCSIDevices[i][j].LunType = SCSI_DISK; + } + else if (find_cdrom_for_scsi_id(i, j) != 0xff) { + SCSIDevices[i][j].LunType = SCSI_CDROM; + } + else + { + SCSIDevices[i][j].LunType = SCSI_NONE; + } } - else if (find_cdrom_for_scsi_id(i, j) != 0xff) { - SCSIDevices[i][j].LunType = SCSI_CDROM; - } - else { - SCSIDevices[i][j].LunType = SCSI_NONE; - } - } } timer_add(BuslogicResetPoll, @@ -2307,7 +3281,7 @@ BuslogicInit(int chip) pclog("Buslogic on port 0x%04X\n", bl->Base); BuslogicResetControl(bl, CTRL_HRST); - + return(bl); } @@ -2408,6 +3382,9 @@ static device_config_t BuslogicConfig[] = { } }, }, + { + "bios", "Enable BIOS", CONFIG_BINARY, "", 0 + }, { "", "", -1 } diff --git a/src/scsi_disk.c b/src/scsi_disk.c index a3b8c7dda..1a7c95a65 100644 --- a/src/scsi_disk.c +++ b/src/scsi_disk.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "86box.h" #include "cdrom.h" @@ -115,11 +116,12 @@ uint8_t scsi_hd_command_flags[0x100] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +/* #define ENABLE_SCSI_HD_LOG 0 */ int scsi_hd_do_log = 0; void scsi_hd_log(const char *format, ...) { -#ifdef ENABLE_scsi_hd_LOG +#ifdef ENABLE_SCSI_HD_LOG if (scsi_hd_do_log) { va_list ap; @@ -291,7 +293,13 @@ int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *l buffer[3] = size & 0xff; buffer[6] = 2; /* 512 = 0x0200 */ *len = 8; - + + pclog("Read Capacity\n"); + pclog("buffer[0]=%x\n", buffer[0]); + pclog("buffer[1]=%x\n", buffer[1]); + pclog("buffer[2]=%x\n", buffer[2]); + pclog("buffer[3]=%x\n", buffer[3]); + return 1; } @@ -353,7 +361,7 @@ static void scsi_hd_command_common(uint8_t id) } } -static void scsi_hd_command_complete(uint8_t id) +void scsi_hd_command_complete(uint8_t id) { shdc[id].packet_status = CDROM_PHASE_COMPLETE; scsi_hd_command_common(id); @@ -372,7 +380,7 @@ static void scsi_hd_command_write_dma(uint8_t id) scsi_hd_command_common(id); } -static void scsi_hd_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +void scsi_hd_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) { scsi_hd_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, shdc[id].current_cdb[0], len, block_len, alloc_len, direction, shdc[id].request_length); shdc[id].pos=0; @@ -470,7 +478,7 @@ static void scsi_hd_illegal_opcode(uint8_t id) scsi_hd_cmd_error(id); } -static void scsi_hd_lba_out_of_range(uint8_t id) +void scsi_hd_lba_out_of_range(uint8_t id) { scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; scsi_hd_asc = ASC_LBA_OUT_OF_RANGE; @@ -792,7 +800,6 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) case GPCMD_READ_10: shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; shdc[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); break; case GPCMD_READ_12: shdc[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); diff --git a/src/scsi_disk.h b/src/scsi_disk.h index db3ea9848..7d5b23e85 100644 --- a/src/scsi_disk.h +++ b/src/scsi_disk.h @@ -52,3 +52,5 @@ extern void scsi_reloadhd(int id); extern void scsi_unloadhd(int scsi_id, int scsi_lun, int id); extern FILE *shdf[HDC_NUM]; + +int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); From 28019344cc3ef12bf0dbc2aa0340e188bdf5e760 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 15 Aug 2017 21:09:35 +0200 Subject: [PATCH 76/82] Cleanup of the Adaptec 154xB code and added the port 0x330 bios. Fixed CPU id in the Pentium at 100Mhz. --- src/CPU/cpu.c | 8 +- src/scsi_aha154x.c | 200 +++++++++++++++++---------------------------- 2 files changed, 77 insertions(+), 131 deletions(-) diff --git a/src/CPU/cpu.c b/src/CPU/cpu.c index f8f4c9c76..10b06fd83 100644 --- a/src/CPU/cpu.c +++ b/src/CPU/cpu.c @@ -494,8 +494,8 @@ CPU cpus_PentiumS5[] = {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, + {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7}, {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, @@ -514,8 +514,8 @@ CPU cpus_Pentium[] = {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, + {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index cbb5554b5..062c120d6 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -150,7 +150,7 @@ #define CMD_NOP 0x00 /* No operation */ #define CMD_MBINIT 0x01 /* mailbox initialization */ #define CMD_START_SCSI 0x02 /* Start SCSI command */ -#define CMD_BIOS 0x03 /* Execute ROM BIOS command */ +#define CMD_BIOSCMD 0x03 /* Execute ROM BIOS command */ #define CMD_INQUIRY 0x04 /* Adapter inquiry */ #define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */ #define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */ @@ -162,6 +162,18 @@ #define CMD_TARGET 0x0C /* set HBA to target mode */ #define CMD_RETSETUP 0x0D /* return setup data */ #define CMD_ECHO 0x1F /* ECHO command data */ +#define CMD_OPTIONS 0x21 /* set adapter options */ +#define CMD_EXTBIOS 0x28 // return extended BIOS information +#define CMD_MBENABLE 0x29 // set mailbox interface enable + +/* Undocumented commands */ +#define CMD_WRITE_EEPROM 0x22 /* Write EEPROM */ +#define CMD_READ_EEPROM 0x23 /* Read EEPROM */ +#define CMD_SHADOW_RAM 0x24 /* BIOS shadow ram */ +#define CMD_BIOS_MBINIT 0x25 /* BIOS mailbox initialization */ +#define CMD_MEMORY_MAP_1 0x26 /* Memory Mapper */ +#define CMD_MEMORY_MAP_2 0x27 /* Memory Mapper */ +#define CMD_BIOS_SCSI 0x82 /* Start ROM BIOS SCSI command */ /* READ INTERRUPT STATUS. */ #define INTR_ANY 0x80 /* any interrupt */ @@ -938,32 +950,6 @@ RaiseIntr(aha_t *dev, uint8_t Interrupt) } } - -static void -LocalRAM(aha_t *dev) -{ - /* - * These values are mostly from what I think is right - * looking at the dmesg output from a Linux guest inside - * a VMware server VM. - * - * So they don't have to be right :) - */ - memset(dev->LocalRAM.u8View, 0, sizeof(HALocalRAM)); - dev->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; - dev->LocalRAM.structured.autoSCSIData.fParityCheckingEnabled = 1; - dev->LocalRAM.structured.autoSCSIData.fExtendedTranslation = 1; /* Same as in geometry register. */ - dev->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = UINT16_MAX; /* All enabled. Maybe mask out non present devices? */ - dev->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = UINT16_MAX; - dev->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = UINT16_MAX; - dev->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = UINT16_MAX; - dev->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = UINT16_MAX; - dev->LocalRAM.structured.autoSCSIData.fStrictRoundRobinMode = dev->StrictRoundRobinMode; - dev->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = UINT16_MAX; - /** @todo calculate checksum? */ -} - - static void aha_reset(aha_t *dev) { @@ -986,7 +972,8 @@ aha_reset(aha_t *dev) ClearIntr(dev); - LocalRAM(dev); + /* I think the "local RAM" commands are for the Buslogic, not Adaptec. */ + //LocalRAM(dev); } @@ -1008,7 +995,7 @@ aha_cmd_done(aha_t *dev) dev->DataReply = 0; dev->Status |= STAT_IDLE; - if ((dev->Command != 0x02) && (dev->Command != 0x82)) { + if ((dev->Command != CMD_START_SCSI) && (dev->Command != CMD_BIOS_SCSI)) { dev->Status &= ~STAT_DFULL; dev->Interrupt = (INTR_ANY | INTR_HACC); pclog("Raising IRQ %i\n", dev->Irq); @@ -1345,9 +1332,10 @@ aha_read(uint16_t port, void *priv) break; case 1: - if (dev->UseLocalRAM) - ret = dev->LocalRAM.u8View[dev->DataReply]; - else + /* Local RAM is for Buslogic or unsupported Adaptec models */ + //if (dev->UseLocalRAM) + // ret = dev->LocalRAM.u8View[dev->DataReply]; + //else ret = dev->DataBuf[dev->DataReply]; if (dev->DataReplyLeft) { dev->DataReply++; @@ -1387,7 +1375,6 @@ aha_write(uint16_t port, uint8_t val, void *priv) int i = 0; uint8_t j = 0; aha_t *dev = (aha_t *)priv; - uint8_t Offset; MailboxInit_t *MailboxInit; BIOSCMD *BiosCmd; ReplyInquireSetupInformation *ReplyISI; @@ -1412,12 +1399,12 @@ aha_write(uint16_t port, uint8_t val, void *priv) case 1: /* Fast path for the mailbox execution command. */ - if (((val == 0x02) || (val == 0x82)) && + if (((val == CMD_START_SCSI) || (val == CMD_BIOS_SCSI)) && (dev->Command == 0xFF)) { /* If there are no mailboxes configured, don't even try to do anything. */ if (dev->MailboxCount) { if (!AHA_Callback) { - AHA_Callback = 1 * TIMER_USEC; + AHA_Callback = SCSI_DELAY_TM * TIMER_USEC; } } return; @@ -1431,52 +1418,43 @@ aha_write(uint16_t port, uint8_t val, void *priv) dev->Status &= ~(STAT_INVCMD | STAT_IDLE); pclog("AHA154X: Operation Code 0x%02X\n", val); switch (dev->Command) { - case 0x01: + case CMD_MBINIT: dev->CmdParamLeft = sizeof(MailboxInit_t); break; - case 0x03: /* Exec BIOS Command */ + case CMD_BIOSCMD: dev->CmdParamLeft = 10; break; - case 0x25: + case CMD_BIOS_MBINIT: /* Same as 0x01 for AHA. */ dev->CmdParamLeft = sizeof(MailboxInit_t); break; - case 0x05: - case 0x07: - case 0x08: - case 0x09: - case 0x0D: - case 0x1F: - case 0x21: - case 0x24: + case CMD_EMBOI: + case CMD_BUSON_TIME: + case CMD_BUSOFF_TIME: + case CMD_DMASPEED: + case CMD_RETSETUP: + case CMD_ECHO: + case CMD_OPTIONS: + case CMD_SHADOW_RAM: dev->CmdParamLeft = 1; break; - case 0x06: + case CMD_SELTIMEOUT: dev->CmdParamLeft = 4; break; - case 0x1C: - case 0x1D: - dev->CmdParamLeft = 3; - break; - - case 0x22: /* write EEPROM */ + case CMD_WRITE_EEPROM: dev->CmdParamLeft = 3+32; break; - case 0x23: /* read EEPROM */ + case CMD_READ_EEPROM: dev->CmdParamLeft = 3; break; - case 0x29: - dev->CmdParamLeft = 2; - break; - - case 0x91: + case CMD_MBENABLE: dev->CmdParamLeft = 2; break; } @@ -1489,11 +1467,11 @@ aha_write(uint16_t port, uint8_t val, void *priv) if (! dev->CmdParamLeft) { pclog("Running Operation Code 0x%02X\n", dev->Command); switch (dev->Command) { - case 0x00: + case CMD_NOP: /* No Operation Command */ dev->DataReplyLeft = 0; break; - case 0x01: + case CMD_MBINIT: /* Mailbox Initialitation */ aha_0x01: { dev->Mbx24bit = 1; @@ -1514,7 +1492,7 @@ aha_0x01: } break; - case 0x03: + case CMD_BIOSCMD: /* Execute BIOS Command */ BiosCmd = (BIOSCMD *)dev->CmdBuf; cyl = ((BiosCmd->cylinder & 0xff) << 8) | ((BiosCmd->cylinder >> 8) & 0xff); @@ -1528,7 +1506,7 @@ aha_0x01: dev->DataReplyLeft = 1; break; - case 0x04: + case CMD_INQUIRY: /* Inquiry Command */ dev->DataBuf[0] = (dev->chip != CHIP_AHA1640) ? dev->aha.bid : 0x42; dev->DataBuf[1] = (dev->chip != CHIP_AHA1640) ? 0x30 : 0x42; dev->DataBuf[2] = dev->aha.fwh; @@ -1536,7 +1514,7 @@ aha_0x01: dev->DataReplyLeft = 4; break; - case 0x05: + case CMD_EMBOI: /* Enable Mailbox Out Interrupt */ if (dev->CmdBuf[0] <= 1) { dev->MailboxOutInterrupts = dev->CmdBuf[0]; pclog("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); @@ -1546,29 +1524,26 @@ aha_0x01: dev->DataReplyLeft = 0; break; - case 0x06: + case CMD_SELTIMEOUT: /* Selection Time-out */ dev->DataReplyLeft = 0; break; - case 0x07: + case CMD_BUSON_TIME: /* Bus-on time */ dev->DataReplyLeft = 0; - dev->LocalRAM.structured.autoSCSIData.uBusOnDelay = dev->CmdBuf[0]; pclog("Bus-on time: %d\n", dev->CmdBuf[0]); break; - case 0x08: + case CMD_BUSOFF_TIME: /* Bus-off time */ dev->DataReplyLeft = 0; - dev->LocalRAM.structured.autoSCSIData.uBusOffDelay = dev->CmdBuf[0]; pclog("Bus-off time: %d\n", dev->CmdBuf[0]); break; - case 0x09: + case CMD_DMASPEED: /* DMA Transfer Rate Command */ dev->DataReplyLeft = 0; - dev->LocalRAM.structured.autoSCSIData.uDMATransferRate = dev->CmdBuf[0]; pclog("DMA transfer rate: %02X\n", dev->CmdBuf[0]); break; - case 0x0A: + case CMD_RETDEVS: /* Return Installed Devices */ memset(dev->DataBuf, 0, 8); for (i=0; i<7; i++) { dev->DataBuf[i] = 0; @@ -1581,7 +1556,7 @@ aha_0x01: dev->DataReplyLeft = 8; break; - case 0x0B: + case CMD_RETCONF: /* Return Configuration Command */ dev->DataBuf[0] = (1<DmaChannel); if (dev->Irq >= 8) dev->DataBuf[1]=(1<<(dev->Irq-9)); @@ -1591,7 +1566,7 @@ aha_0x01: dev->DataReplyLeft = 3; break; - case 0x0D: + case CMD_RETSETUP: /* Return Setup Command */ { dev->DataReplyLeft = dev->CmdBuf[0]; @@ -1605,48 +1580,19 @@ aha_0x01: pclog("Return Setup Information: %d\n", dev->CmdBuf[0]); } break; - - case 0x1C: - { - uint32_t FIFOBuf; - addr24 Address; - - dev->DataReplyLeft = 0; - Address.hi = dev->CmdBuf[0]; - Address.mid = dev->CmdBuf[1]; - Address.lo = dev->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - DMAPageRead(FIFOBuf, (char *)&dev->LocalRAM.u8View[64], 64); - } - break; - case 0x1D: - { - uint32_t FIFOBuf; - addr24 Address; - - dev->DataReplyLeft = 0; - Address.hi = dev->CmdBuf[0]; - Address.mid = dev->CmdBuf[1]; - Address.lo = dev->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - pclog("FIFO: Writing 64 bytes at %08X\n", FIFOBuf); - DMAPageWrite(FIFOBuf, (char *)&dev->LocalRAM.u8View[64], 64); - } - break; - - case 0x1F: + case CMD_ECHO: /* ECHO data Command */ dev->DataBuf[0] = dev->CmdBuf[0]; dev->DataReplyLeft = 1; break; - case 0x21: + case CMD_OPTIONS: /* Set adapter options */ if (dev->CmdParam == 1) dev->CmdParamLeft = dev->CmdBuf[0]; dev->DataReplyLeft = 0; break; - case 0x22: /* write EEPROM */ + case CMD_WRITE_EEPROM: /* write EEPROM */ /* Sent by CF BIOS. */ dev->DataReplyLeft = aha154x_eeprom(dev->Command, @@ -1661,7 +1607,8 @@ aha_0x01: } break; - case 0x23: + case CMD_READ_EEPROM: /* read EEPROM */ + /* Sent by CF BIOS. */ dev->DataReplyLeft = aha154x_eeprom(dev->Command, dev->CmdBuf[0], @@ -1675,7 +1622,7 @@ aha_0x01: } break; - case 0x24: + case CMD_SHADOW_RAM: /* Shadow RAM */ /* * For AHA1542CF, this is the command * to play with the Shadow RAM. BIOS @@ -1686,21 +1633,24 @@ aha_0x01: dev->Interrupt = aha154x_shram(val, dev->chip); break; - case 0x25: + case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialitation Command */ + /* Sent by CF BIOS. */ goto aha_0x01; - case 0x26: /* AHA memory mapper */ - case 0x27: /* AHA memory mapper */ + case CMD_MEMORY_MAP_1: /* AHA memory mapper */ + case CMD_MEMORY_MAP_2: /* AHA memory mapper */ + /* Sent by CF BIOS. */ dev->DataReplyLeft = aha154x_memory(dev->Command); break; - case 0x28: + case CMD_EXTBIOS: /* Return extended BIOS information */ dev->DataBuf[0] = 0x08; dev->DataBuf[1] = dev->Lock; dev->DataReplyLeft = 2; break; - case 0x29: + + case CMD_MBENABLE: /* Mailbox interface enable Command */ dev->DataReplyLeft = 0; if (dev->CmdBuf[1] == dev->Lock) { if (dev->CmdBuf[0] & 1) { @@ -1724,14 +1674,6 @@ aha_0x01: dev->DataReplyLeft = 256; break; - case 0x91: - Offset = dev->CmdBuf[0]; - dev->DataReplyLeft = dev->CmdBuf[1]; - - dev->UseLocalRAM = 1; - dev->DataReply = Offset; - break; - default: dev->DataReplyLeft = 0; dev->Status |= STAT_INVCMD; @@ -2162,7 +2104,7 @@ aha_cmd_cb(void *priv) if (dev->MailboxCount) { aha_do_mail(dev); } else { - AHA_Callback += 1 * TIMER_USEC; + AHA_Callback += SCSI_DELAY_TM * TIMER_USEC; return; } } else if (AHA_InOperation == 1) { @@ -2186,7 +2128,7 @@ aha_cmd_cb(void *priv) fatal("Invalid BusLogic callback phase: %i\n", AHA_InOperation); } - AHA_Callback += 1 * TIMER_USEC; + AHA_Callback += SCSI_DELAY_TM * TIMER_USEC; } uint8_t aha_mca_read(int port, void *p) @@ -2261,7 +2203,7 @@ aha_device_reset(void *p) static void * -aha_init(int chip, int has_bios) +aha_init(int chip) { aha_t *dev; int i = 0; @@ -2316,7 +2258,11 @@ aha_init(int chip, int has_bios) /* Perform AHA-154xNN-specific initialization. */ if (chip == CHIP_AHA154XB) { - rom_init(&dev->bios, L"roms/scsi/adaptec/B_AC00.BIN", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + /* Adaptec 154xB AT/SCSI BIOS Version 3.20 with support for over 1GB drives */ + if (dev->Base == 0x334 && bios_addr == 0xd8000) /* This BIOS is hardcoded to port 0x334 and address 0xD8000, otherwise it won't work */ + rom_init(&dev->bios, L"roms/scsi/adaptec/B_AC00.BIN", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + else if (dev->Base == 0x330 && bios_addr == 0xd0000) /* This BIOS is hardcoded to port 0x330 and address 0xD0000, otherwise it won't work */ + rom_init(&dev->bios, L"roms/scsi/adaptec/bios_3.2.BIN", 0xd0000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); } else { @@ -2331,14 +2277,14 @@ aha_init(int chip, int has_bios) static void * aha_154xB_init(void) { - return(aha_init(CHIP_AHA154XB, 0)); + return(aha_init(CHIP_AHA154XB)); } static void * aha_154xCF_init(void) { - return(aha_init(CHIP_AHA154XCF, 1)); + return(aha_init(CHIP_AHA154XCF)); } static void * From b918ee2b477bcd19934fff24dfe0954246a5c8ce Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 16 Aug 2017 01:04:44 +0200 Subject: [PATCH 77/82] Correctly implemented the CMPXCHG8B instruction for the WinChip. --- src/CPU/386_ops.h | 8 ++++---- src/CPU/808x.c | 2 ++ src/CPU/codegen_timing_winchip.c | 4 ++-- src/CPU/cpu.c | 10 +++------- src/CPU/cpu.h | 10 ++++++++++ 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/CPU/386_ops.h b/src/CPU/386_ops.h index 17d27c7fb..edae86201 100644 --- a/src/CPU/386_ops.h +++ b/src/CPU/386_ops.h @@ -519,7 +519,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, /*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, /*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, @@ -541,7 +541,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, /*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, /*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, @@ -563,7 +563,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, @@ -585,7 +585,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, diff --git a/src/CPU/808x.c b/src/CPU/808x.c index 6ff59cbd3..3b21dc4dc 100644 --- a/src/CPU/808x.c +++ b/src/CPU/808x.c @@ -571,6 +571,7 @@ void resetx86() cpu_cur_status = 0; stack32=0; cpu_state.pc=0; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw=0; if (is486) cr0 = 1 << 30; @@ -609,6 +610,7 @@ void softresetx86() stack32=0; cpu_cur_status = 0; cpu_state.pc=0; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw=0; cr0=0; cr4 = 0; diff --git a/src/CPU/codegen_timing_winchip.c b/src/CPU/codegen_timing_winchip.c index 291a5b435..2726bbcc9 100644 --- a/src/CPU/codegen_timing_winchip.c +++ b/src/CPU/codegen_timing_winchip.c @@ -74,7 +74,7 @@ static int *opcode_timings_0f[256] = /*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30), /*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3), -/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), /*d0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, /*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, /*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, @@ -96,7 +96,7 @@ static int *opcode_timings_0f_mod3[256] = /*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30), /*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3), -/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), /*d0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, /*e0*/ NULL, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, /*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, diff --git a/src/CPU/cpu.c b/src/CPU/cpu.c index 10b06fd83..dbc746cac 100644 --- a/src/CPU/cpu.c +++ b/src/CPU/cpu.c @@ -162,13 +162,7 @@ int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer; int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; int timing_misaligned; -static struct -{ - uint32_t tr1, tr12; - uint32_t cesr; - uint32_t fcr; - uint64_t fcr2, fcr3; -} msr; +msr_t msr; /*Available cpuspeeds : 0 = 16 MHz @@ -1671,6 +1665,8 @@ void cpu_CPUID() EAX = 0x540; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (msr.fcr & (1 << 1)) + EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) EDX |= CPUID_MMX; } diff --git a/src/CPU/cpu.h b/src/CPU/cpu.h index a786adf3c..0cdc29513 100644 --- a/src/CPU/cpu.h +++ b/src/CPU/cpu.h @@ -187,4 +187,14 @@ extern int isa_cycles; void cpu_update_waitstates(); void cpu_set(); +typedef struct +{ + uint32_t tr1, tr12; + uint32_t cesr; + uint32_t fcr; + uint64_t fcr2, fcr3; +} msr_t; + +extern msr_t msr; + #endif From 2d1fe7b52c5c0fec6a459d92f64884441219a703 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 16 Aug 2017 01:19:25 +0200 Subject: [PATCH 78/82] Properly loaded the correct Adaptec 154xB bioses, leaving "aha154x_bios()" only for the C and CF bioses if needed. --- src/scsi_aha154x.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index 062c120d6..5ce5d8a0c 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -194,8 +194,6 @@ static uint16_t aha_ports[] = { 0x0130, 0x0134, 0x0000, 0x0000 }; -#define WALTJE 1 - #ifdef WALTJE int aha_do_log = 1; # define ENABLE_AHA154X_LOG @@ -321,15 +319,7 @@ aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha, int irq, int dma, /* Set BIOS load address. */ bios_addr = memaddr; /* bios_path = ROMFILE; */ - if (chip == CHIP_AHA154XB) - { - /* bios_path = L"roms/scsi/adaptec/aha1540b310.bin"; */ - bios_path = L"roms/scsi/adaptec/B_AC00.BIN"; - } - else - { bios_path = L"roms/scsi/adaptec/aha1542cf201.bin"; - } pclog_w(L"AHA154x: loading BIOS from '%s'\n", bios_path); /* Open the BIOS image file and make sure it exists. */ From 4fa634737e2053ff4243c883ac566518b16c1576 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 16 Aug 2017 01:48:24 +0200 Subject: [PATCH 79/82] Fixed the MIDI device selection combo box on Settings dialog page initialization. --- src/WIN/win_settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WIN/win_settings.c b/src/WIN/win_settings.c index d619d3917..9c27da4ea 100644 --- a/src/WIN/win_settings.c +++ b/src/WIN/win_settings.c @@ -1259,7 +1259,7 @@ static BOOL CALLBACK win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wPa c++; } - SendMessage(h, CB_SETCURSEL, settings_sound_to_list[temp_midi_device], 0); + SendMessage(h, CB_SETCURSEL, settings_midi_to_list[temp_midi_device], 0); h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI); if (midi_device_has_config(temp_midi_device)) From d4f4a781cf3139b76fef05eb7ea90af0b859405a Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 16 Aug 2017 02:33:25 +0200 Subject: [PATCH 80/82] The EuroPC now uses a NVR file; The EuroPC now includes a LPT3 port. --- src/lpt.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- src/lpt.h | 2 ++ src/model.c | 3 ++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/lpt.c b/src/lpt.c index eb25900af..d8458b28e 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -6,8 +6,8 @@ #include "lpt.h" -static uint8_t lpt1_dat, lpt2_dat; -static uint8_t lpt1_ctrl, lpt2_ctrl; +static uint8_t lpt1_dat, lpt2_dat, lpt3_dat; +static uint8_t lpt1_ctrl, lpt2_ctrl, lpt3_ctrl; void lpt1_write(uint16_t port, uint8_t val, void *priv) { @@ -57,7 +57,31 @@ uint8_t lpt2_read(uint16_t port, void *priv) return 0xff; } -uint16_t lpt_addr[2] = { 0x378, 0x278 }; +void lpt3_write(uint16_t port, uint8_t val, void *priv) +{ + switch (port & 3) + { + case 0: + lpt3_dat = val; + break; + case 2: + lpt3_ctrl = val; + break; + } +} +uint8_t lpt3_read(uint16_t port, void *priv) +{ + switch (port & 3) + { + case 0: + return lpt3_dat; + case 2: + return lpt3_ctrl; + } + return 0xff; +} + +uint16_t lpt_addr[3] = { 0x378, 0x278, 0x3bc }; void lpt_init() { @@ -108,3 +132,19 @@ void lpt2_remove_ams() io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); } } + +void lpt3_init(uint16_t port) +{ + if (lpt_enabled) + { + io_sethandler(port, 0x0003, lpt3_read, NULL, NULL, lpt3_write, NULL, NULL, NULL); + lpt_addr[2] = port; + } +} +void lpt3_remove() +{ + if (lpt_enabled) + { + io_removehandler(lpt_addr[2], 0x0003, lpt3_read, NULL, NULL, lpt3_write, NULL, NULL, NULL); + } +} diff --git a/src/lpt.h b/src/lpt.h index d1ed96801..78968b5a3 100644 --- a/src/lpt.h +++ b/src/lpt.h @@ -7,3 +7,5 @@ extern void lpt1_remove(); extern void lpt2_init(uint16_t port); extern void lpt2_remove(); extern void lpt2_remove_ams(); +extern void lpt3_init(uint16_t port); +extern void lpt3_remove(); diff --git a/src/model.c b/src/model.c index 018d7fe05..e86bd09a6 100644 --- a/src/model.c +++ b/src/model.c @@ -148,7 +148,7 @@ MODEL models[] = {"[8088] Generic XT clone", ROM_GENXT, "genxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, xt_init, NULL }, {"[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, xt_init, NULL }, {"[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, xt_init, NULL }, - {"[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 512, 640, 128, 0, europc_init, NULL }, + {"[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 512, 640, 128, 63, europc_init, NULL }, {"[8088] Tandy 1000", ROM_TANDY, "tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, 0, 128, 640, 128, 0, tandy1k_init, &tandy1000_device }, {"[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, 0, 256, 640, 128, 0, tandy1k_init, &tandy1000hx_device }, {"[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 1152, 64, 0, xt_laserxt_init, NULL }, @@ -395,6 +395,7 @@ void europc_init(void) { common_init(); mem_add_bios(); + lpt3_init(); jim_init(); keyboard_xt_init(); nmi_init(); From 0915db67d51d4a05d2bff6a1f4fdd07bb3aace16 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 16 Aug 2017 21:46:32 +0200 Subject: [PATCH 81/82] Fixed LPT3 initialization in model.c, this should make it compile again. --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index e86bd09a6..7980dcc88 100644 --- a/src/model.c +++ b/src/model.c @@ -395,7 +395,7 @@ void europc_init(void) { common_init(); mem_add_bios(); - lpt3_init(); + lpt3_init(0x3bc); jim_init(); keyboard_xt_init(); nmi_init(); From 6dbdc0483fd6c033220f2342015b61bb9e5675cc Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 17 Aug 2017 23:16:26 +0200 Subject: [PATCH 82/82] The RTL8029AS Expansion ROM BAR PCI registers are now implemented correctly; The BusLogic BT-958D PCI SCSI controller now optionally uses a BIOS (supports up to eight SCSI hard disks, up to 8 GB each); Fixed some BusLogic commands; The BusLogic SCSI controllers now use 15 as the host adapter ID. --- src/NETWORK/net_ne2000.c | 37 +++++--- src/scsi_buslogic.c | 194 ++++++++++++++++++++++++++++++--------- 2 files changed, 176 insertions(+), 55 deletions(-) diff --git a/src/NETWORK/net_ne2000.c b/src/NETWORK/net_ne2000.c index 0b3a04de8..c77b1c745 100644 --- a/src/NETWORK/net_ne2000.c +++ b/src/NETWORK/net_ne2000.c @@ -217,6 +217,7 @@ typedef struct { uint8_t eeprom[128]; /* for RTL8029AS */ rom_t bios_rom; int card; /* PCI card slot */ + int has_bios; } nic_t; @@ -1426,19 +1427,23 @@ nic_update_bios(nic_t *dev) int reg_bios_enable; reg_bios_enable = 1; + + if (!dev->has_bios) { + return; + } + + if (PCI && dev->is_pci) { + reg_bios_enable = dev->pci_bar[1].addr_regs[0] & 0x01; + } /* PCI BIOS stuff, just enable_disable. */ - if ((dev->bios_addr > 0) && reg_bios_enable) { - mem_mapping_enable(&dev->bios_rom.mapping); + if (reg_bios_enable) { mem_mapping_set_addr(&dev->bios_rom.mapping, dev->bios_addr, dev->bios_size); nelog(1, "%s: BIOS now at: %06X\n", dev->name, dev->bios_addr); } else { nelog(1, "%s: BIOS disabled\n", dev->name); mem_mapping_disable(&dev->bios_rom.mapping); - dev->bios_addr = 0; - if (dev->is_pci) - dev->pci_bar[1].addr = 0; } } @@ -1527,7 +1532,7 @@ nic_pci_read(int func, int addr, void *priv) ret = dev->pci_bar[1].addr_regs[0] & 0x01; break; case 0x31: /* PCI_ROMBAR 15:11 */ - ret = (dev->pci_bar[1].addr_regs[1] & dev->bios_mask) | 0x18; + ret = (dev->pci_bar[1].addr_regs[1] & dev->bios_mask); break; case 0x32: /* PCI_ROMBAR 23:16 */ ret = dev->pci_bar[1].addr_regs[2]; @@ -1632,9 +1637,8 @@ nic_pci_write(int func, int addr, uint8_t val, void *priv) case 0x33: /* PCI_ROMBAR */ dev->pci_bar[1].addr_regs[addr & 3] = val; dev->pci_bar[1].addr_regs[1] &= dev->bios_mask; - dev->pci_bar[1].addr &= 0xffffe000; + dev->pci_bar[1].addr &= 0xffffe001; dev->bios_addr = dev->pci_bar[1].addr; - dev->pci_bar[1].addr |= 0x1801; nic_update_bios(dev); return; @@ -1917,10 +1921,19 @@ nic_init(int board) dev->base_irq = 10; } else { dev->base_address = device_get_config_hex16("base"); - dev->bios_addr = device_get_config_hex20("bios_addr"); dev->base_irq = device_get_config_int("irq"); } + dev->bios_addr = device_get_config_hex20("bios_addr"); + if (dev->bios_addr) + { + dev->has_bios = 1; + } + else + { + dev->has_bios = 0; + } + /* See if we have a local MAC address configured. */ mac = device_get_config_mac("mac", -1); @@ -1962,11 +1975,13 @@ nic_init(int board) if (dev->bios_addr > 0) { dev->pci_bar[1].addr = 0x000F8000; dev->pci_bar[1].addr_regs[1] = dev->bios_mask; - dev->pci_bar[1].addr |= 0x1801; } else { dev->pci_bar[1].addr = 0; + dev->bios_size = 0; } + mem_mapping_disable(&dev->bios_rom.mapping); + /* Initialize the RTL8029 EEPROM. */ memset(dev->eeprom, 0x00, sizeof(dev->eeprom)); dev->eeprom[0x76] = @@ -2225,7 +2240,6 @@ static device_config_t ne2000_config[] = static device_config_t rtl8029as_config[] = { -#if 1 /* * WTF. * Even though it is PCI, the user should still have control @@ -2252,7 +2266,6 @@ static device_config_t rtl8029as_config[] = } }, }, -#endif { "mac", "MAC Address", CONFIG_MAC, "", -1 }, diff --git a/src/scsi_buslogic.c b/src/scsi_buslogic.c index 25ad0e928..7b2c1b21f 100644 --- a/src/scsi_buslogic.c +++ b/src/scsi_buslogic.c @@ -10,7 +10,7 @@ * 0 - BT-542B ISA; * 1 - BT-958 PCI (but BT-542B ISA on non-PCI machines) * - * Version: @(#)scsi_buslogic.c 1.0.5 2017/08/15 + * Version: @(#)scsi_buslogic.c 1.0.6 2017/08/17 * * Authors: TheCollector1995, * Miran Grca, @@ -513,7 +513,10 @@ typedef struct { mem_mapping_t mmio_mapping; int chip; int Card; - int has_bios; + int has_bios; + uint32_t bios_addr, + bios_size, + bios_mask; } Buslogic_t; #pragma pack(pop) @@ -580,12 +583,12 @@ BuslogicInterrupt(Buslogic_t *bl, int set) if (set) { picint(1 << bl->Irq); - //pclog("Interrupt Set\n"); + /* pclog("Interrupt Set\n"); */ } else { picintc(1 << bl->Irq); - //pclog("Interrupt Cleared\n"); + /* pclog("Interrupt Cleared\n"); */ } } } @@ -594,13 +597,13 @@ BuslogicInterrupt(Buslogic_t *bl, int set) static void BuslogicClearInterrupt(Buslogic_t *bl) { - //pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); + /* pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); */ bl->Interrupt = 0; - //pclog("Lowering IRQ %i\n", bl->Irq); + /* pclog("Lowering IRQ %i\n", bl->Irq); */ BuslogicInterrupt(bl, 0); if (bl->PendingInterrupt) { bl->Interrupt = bl->PendingInterrupt; - //pclog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", bl->Interrupt); + /* pclog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", bl->Interrupt); */ if (bl->MailboxOutInterrupts || !(bl->Interrupt & INTR_MBOA)) { if (bl->IrqEnabled) BuslogicInterrupt(bl, 1); } @@ -611,7 +614,7 @@ BuslogicClearInterrupt(Buslogic_t *bl) static void BuslogicReset(Buslogic_t *bl) { - //pclog("BuslogicReset()\n"); + /* pclog("BuslogicReset()\n"); */ BuslogicCallback = 0; BuslogicResetCallback = 0; bl->Geometry = 0x80; @@ -636,7 +639,7 @@ BuslogicReset(Buslogic_t *bl) static void BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) { - //pclog("BuslogicResetControl()\n"); + /* pclog("BuslogicResetControl()\n"); */ BuslogicReset(bl); if (Reset) { bl->Status |= STAT_STST; @@ -1108,11 +1111,10 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf uint8_t cdrom_id, cdrom_phase; uint32_t i; uint8_t temp_cdb[12]; - uint8_t last_id = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7; DataInBuf[0] = DataInBuf[1] = 0; - if ((ESCSICmd->TargetId > last_id) || (ESCSICmd->LogicalUnit > 7)) { + if ((ESCSICmd->TargetId > 15) || (ESCSICmd->LogicalUnit > 7)) { DataInBuf[2] = CCB_INVALID_CCB; DataInBuf[3] = SCSI_STATUS_OK; return; @@ -1128,7 +1130,7 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType == SCSI_NONE) { SpecificLog("SCSI Target ID %i and LUN %i have no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit); BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - //BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, 0, 0); + /* BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, 0, 0); */ DataInBuf[2] = CCB_SELECTION_TIMEOUT; DataInBuf[3] = SCSI_STATUS_OK; } else { @@ -1203,7 +1205,7 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf pclog("SCSI Status: %s, Sense: %02X, ASC: %02X, ASCQ: %02X\n", (SCSIStatus == SCSI_STATUS_OK) ? "OK" : "CHECK CONDITION", shdc[hdc_id].sense[2], shdc[hdc_id].sense[12], shdc[hdc_id].sense[13]); BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - //BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, (SCSIStatus != SCSI_STATUS_OK), 1); + /* BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, (SCSIStatus != SCSI_STATUS_OK), 1); */ pclog("BIOS Request complete\n"); @@ -1288,7 +1290,7 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf } } - //BuslogicInOperation = (SCSIDevices[Id][Lun].LunType == SCSI_DISK) ? 0x13 : 3; + /* BuslogicInOperation = (SCSIDevices[Id][Lun].LunType == SCSI_DISK) ? 0x13 : 3; */ pclog("SCSI (%i:%i) -> %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType); bl->DataReplyLeft = DataReply; @@ -1961,6 +1963,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */ int cCharsToTransfer; uint16_t cyl = 0; + uint8_t temp = 0; pclog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); @@ -2113,9 +2116,15 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) BiosCmd = (BIOSCMD *)bl->CmdBuf; cyl = ((BiosCmd->cylinder & 0xff) << 8) | ((BiosCmd->cylinder >> 8) & 0xff); - BiosCmd->cylinder = cyl; + BiosCmd->cylinder = cyl; + if (bl->chip == CHIP_BUSLOGIC_PCI) + { + temp = BiosCmd->id; + BiosCmd->id = BiosCmd->lun; + BiosCmd->lun = temp; + } SpecificLog("C: %04X, H: %02X, S: %02X\n", BiosCmd->cylinder, BiosCmd->head, BiosCmd->sector); - bl->DataBuf[0] = HACommand03Handler((bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7, BiosCmd); + bl->DataBuf[0] = HACommand03Handler(15, BiosCmd); SpecificLog("BIOS Completion/Status Code %x\n", bl->DataBuf[0]); bl->DataReplyLeft = 1; break; @@ -2164,14 +2173,13 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x0A: memset(bl->DataBuf, 0, 8); - for (i=0; i<7; i++) { + for (i=0; i<8; i++) { bl->DataBuf[i] = 0; for (j=0; j<8; j++) { if (SCSIDevices[i][j].LunType != SCSI_NONE) bl->DataBuf[i] |= (1 << j); } } - bl->DataBuf[7] = 0; bl->DataReplyLeft = 8; break; @@ -2186,7 +2194,8 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->DataBuf[1] = 0; { } - bl->DataBuf[2] = 7; /* HOST ID */ + /* bl->DataBuf[2] = 7; */ /* HOST ID */ + bl->DataBuf[2] = 15; /* HOST ID */ bl->DataReplyLeft = 3; break; @@ -2224,7 +2233,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Address.lo = bl->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); pclog("Buslogic LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); - DMAPageRead(FIFOBuf, (char *)&bl->LocalRAM.u8View[64], 64); + DMAPageRead(FIFOBuf, (char *)bl->LocalRAM.u8View, 64); } break; @@ -2239,7 +2248,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Address.lo = bl->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); pclog("Buslogic LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); - DMAPageWrite(FIFOBuf, (char *)&bl->LocalRAM.u8View[64], 64); + DMAPageWrite(FIFOBuf, (char *)bl->LocalRAM.u8View, 64); } break; @@ -2261,14 +2270,14 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x23: memset(bl->DataBuf, 0, 8); - for (i = 8; i < 16; i++) { - /* FIXME: Kotori, check this! */ + for (i = 8; i < 15; i++) { bl->DataBuf[i-8] = 0; for (j=0; j<8; j++) { if (SCSIDevices[i][j].LunType != SCSI_NONE) bl->DataBuf[i-8] |= (1<DataBuf[7] = 0; bl->DataReplyLeft = 8; break; @@ -2276,11 +2285,9 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) { uint16_t TargetsPresentMask = 0; - for (i=0; i<16; i++) { - for (j=0; j<8; j++) { - if (SCSIDevices[i][j].LunType != SCSI_NONE) + for (i=0; i<15; i++) { + if (SCSIDevices[i][0].LunType != SCSI_NONE) TargetsPresentMask |= (1 << i); - } } bl->DataBuf[0] = TargetsPresentMask & 0xFF; bl->DataBuf[1] = TargetsPresentMask >> 8; @@ -2420,9 +2427,9 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) ReplyIESI->u16ScatterGatherLimit = 8192; ReplyIESI->cMailbox = bl->MailboxCount; ReplyIESI->uMailboxAddressBase = bl->MailboxOutAddr; + ReplyIESI->fHostWideSCSI = 1; /* This should be set for the BT-542B as well. */ if (bl->chip == CHIP_BUSLOGIC_PCI) { ReplyIESI->fLevelSensitiveInterrupt = 1; - ReplyIESI->fHostWideSCSI = 1; ReplyIESI->fHostUltraSCSI = 1; } memcpy(ReplyIESI->aFirmwareRevision, "21E", sizeof(ReplyIESI->aFirmwareRevision)); @@ -2793,7 +2800,6 @@ BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbox32_t *Mailb { Req_t *req = &bl->Req; uint8_t Id, Lun; - uint8_t last_id = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7; /* Fetch data from the Command Control Block. */ DMAPageRead(CCBPointer, (char *)&req->CmdBlock, sizeof(CCB32)); @@ -2805,7 +2811,7 @@ BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbox32_t *Mailb Id = req->TargetID; Lun = req->LUN; - if ((Id > last_id) || (Lun > 7)) { + if ((Id > 15) || (Lun > 7)) { BuslogicMailboxInSetup(bl, CCBPointer, &req->CmdBlock, CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR); return; @@ -3017,6 +3023,29 @@ uint8_t buslogic_pci_regs[256]; bar_t buslogic_pci_bar[3]; +#if 0 +static void +BuslogicBIOSUpdate(Buslogic_t *bl) +{ + int bios_enabled = buslogic_pci_bar[2].addr_regs[0] & 0x01; + + if (!bl->has_bios) { + return; + } + + /* PCI BIOS stuff, just enable_disable. */ + if ((bl->bios_addr > 0) && bios_enabled) { + mem_mapping_enable(&bl->bios.mapping); + mem_mapping_set_addr(&bl->bios.mapping, + bl->bios_addr, bl->bios_size); + pclog("BT-958D: BIOS now at: %06X\n", bl->bios_addr); + } else { + pclog("BT-958D: BIOS disabled\n"); + mem_mapping_disable(&bl->bios.mapping); + } +} +#endif + static uint8_t BuslogicPCIRead(int func, int addr, void *p) { @@ -3032,9 +3061,9 @@ BuslogicPCIRead(int func, int addr, void *p) case 0x03: return 0x10; case 0x04: - return buslogic_pci_regs[0x04]; /*Respond to IO and memory accesses*/ + return buslogic_pci_regs[0x04] & 0x03; /*Respond to IO and memory accesses*/ case 0x05: - return buslogic_pci_regs[0x05]; + return 0; case 0x07: return 2; case 0x08: @@ -3069,14 +3098,23 @@ BuslogicPCIRead(int func, int addr, void *p) return 0x40; case 0x2F: return 0x10; - case 0x30: - return buslogic_pci_bar[2].addr_regs[0] & 0x01; /*BIOS ROM address*/ - case 0x31: - return buslogic_pci_bar[2].addr_regs[1] | 0x18; - case 0x32: +#if 0 + case 0x30: /* PCI_ROMBAR */ + pclog("BT-958D: BIOS BAR 00 = %02X\n", buslogic_pci_bar[2].addr_regs[0] & 0x01); + return buslogic_pci_bar[2].addr_regs[0] & 0x01; + case 0x31: /* PCI_ROMBAR 15:11 */ + pclog("BT-958D: BIOS BAR 01 = %02X\n", (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask)); + return (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask); + break; + case 0x32: /* PCI_ROMBAR 23:16 */ + pclog("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); return buslogic_pci_bar[2].addr_regs[2]; - case 0x33: + break; + case 0x33: /* PCI_ROMBAR 31:24 */ + pclog("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); return buslogic_pci_bar[2].addr_regs[3]; + break; +#endif case 0x3C: return bl->Irq; case 0x3D: @@ -3169,7 +3207,20 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) } } return; - +#if 0 + case 0x30: /* PCI_ROMBAR */ + case 0x31: /* PCI_ROMBAR */ + case 0x32: /* PCI_ROMBAR */ + case 0x33: /* PCI_ROMBAR */ + buslogic_pci_bar[2].addr_regs[addr & 3] = val; + buslogic_pci_bar[2].addr_regs[1] &= bl->bios_mask; + buslogic_pci_bar[2].addr &= 0xffffe001; + bl->bios_addr = buslogic_pci_bar[2].addr; + pclog("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); + BuslogicBIOSUpdate(bl); + return; +#endif + case 0x3C: buslogic_pci_regs[addr] = val; if (val != 0xFF) { @@ -3189,6 +3240,30 @@ BuslogicDeviceReset(void *p) } +static void +BuslogicInitializeLocalRAM(Buslogic_t *bl) +{ + memset(bl->LocalRAM.u8View, 0, sizeof(HALocalRAM)); + if (PCI && (bl->chip == CHIP_BUSLOGIC_PCI)) + { + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; + } + else + { + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 0; + } + bl->LocalRAM.structured.autoSCSIData.fParityCheckingEnabled = 1; + bl->LocalRAM.structured.autoSCSIData.fExtendedTranslation = 1; + bl->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.fStrictRoundRobinMode = 0; + bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = ~0; +} + + static void * BuslogicInit(int chip) { @@ -3227,10 +3302,28 @@ BuslogicInit(int chip) } } - if (bl->has_bios && bl->chip == CHIP_BUSLOGIC_ISA) + if (bl->has_bios) { - rom_init(&bl->bios, L"roms/scsi/buslogic/542_470.ROM", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - } + bl->bios_size = 0x8000; + + bl->bios_mask = (bl->bios_size >> 8) & 0xff; + bl->bios_mask = (0x100 - bl->bios_mask) & 0xff; + + if(bl->chip == CHIP_BUSLOGIC_ISA) + { + rom_init(&bl->bios, L"roms/scsi/buslogic/542_470.ROM", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + } + else + { + rom_init(&bl->bios, L"roms/scsi/buslogic/494GNPCI.ROM", 0xd8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } + } + else + { + bl->bios_size = 0; + + bl->bios_mask = 0; + } pclog("Building SCSI hard disk map...\n"); build_scsi_hd_map(); @@ -3269,18 +3362,33 @@ BuslogicInit(int chip) buslogic_pci_regs[0x05] = 0; buslogic_pci_regs[0x07] = 2; #endif - buslogic_pci_bar[2].addr = 0; + +#if 0 + /* Enable our BIOS space in PCI, if needed. */ + if (bl->has_bios) + { + buslogic_pci_bar[2].addr = 0x000D8000; + } + else + { + buslogic_pci_bar[2].addr = 0; + } +#endif mem_mapping_add(&bl->mmio_mapping, 0xfffd0000, 0x20, mem_read_null, mem_read_nullw, mem_read_nulll, mem_write_null, mem_write_nullw, mem_write_nulll, NULL, MEM_MAPPING_EXTERNAL, bl); mem_mapping_disable(&bl->mmio_mapping); +#if 0 + mem_mapping_disable(&bl->bios.mapping); +#endif } pclog("Buslogic on port 0x%04X\n", bl->Base); BuslogicResetControl(bl, CTRL_HRST); + BuslogicInitializeLocalRAM(bl); return(bl); }