diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ea4ab4c4f..120185c0f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -22,7 +22,7 @@ on: - "!**/Makefile*" jobs: - mingw: + msys2: name: MSYS2 ${{ matrix.build.name }} build (${{ matrix.environment.msystem }}) runs-on: windows-latest @@ -35,15 +35,30 @@ jobs: fail-fast: false matrix: build: - - name: Regular + - name: Regular ODR + slug: -ODR preset: regular target: install/strip - - name: Debug + - name: Debug ODR + slug: -ODR-Debug preset: debug target: install - - name: Dev + - name: Dev ODR + slug: -ODR-Dev preset: experimental target: install + - name: Regular NDR + slug: -NDR + preset: regularndr + target: install/strip + - name: Debug NDR + slug: -NDR-Debug + preset: debugndr + target: install + - name: Dev NDR + slug: -NDR-Dev + preset: experimentalndr + target: install environment: - msystem: MINGW32 prefix: mingw-w64-i686 @@ -51,6 +66,8 @@ jobs: prefix: mingw-w64-x86_64 - msystem: UCRT64 prefix: mingw-w64-ucrt-x86_64 +# - msystem: CLANG32 +# prefix: mingw-w64-clang-i686 - msystem: CLANG64 prefix: mingw-w64-clang-x86_64 @@ -99,21 +116,36 @@ jobs: matrix: build: - name: Regular ODR + slug: -ODR type: Release + dev-build: off new-dynarec: off strip: --strip - name: Debug ODR - slug: -Debug + slug: -ODR-Debug type: Debug + dev-build: off + new-dynarec: off + - name: Dev ODR + slug: -ODR-Dev + type: Debug + dev-build: on new-dynarec: off - name: Regular NDR slug: -NDR type: Release strip: --strip + dev-build: off new-dynarec: on - name: Debug NDR slug: -NDR-Debug type: Debug + dev-build: off + new-dynarec: on + - name: Dev NDR + slug: -NDR-Dev + type: Debug + dev-build: on new-dynarec: on target: - name: x86 @@ -185,16 +217,38 @@ jobs: fail-fast: false matrix: build: - - name: Debug - slug: -Debug + - name: Regular ODR + slug: -ODR + type: Release dev-build: off new-dynarec: off + strip: --strip + - name: Debug ODR + slug: -ODR-Debug + type: Debug + dev-build: off + new-dynarec: off + - name: Dev ODR + slug: -ODR-Dev + type: Debug + dev-build: on + new-dynarec: off + - name: Regular NDR + slug: -NDR + type: Release + strip: --strip + dev-build: off + new-dynarec: on + - name: Debug NDR + slug: -NDR-Debug + type: Debug + dev-build: off + new-dynarec: on + - name: Dev NDR + slug: -NDR-Dev type: Debug - - name: Dev - slug: -Dev dev-build: on new-dynarec: on - type: Debug steps: - uses: actions/checkout@v2 @@ -218,30 +272,46 @@ jobs: name: '86Box${{ matrix.build.slug }}-Linux-x86_64-gha${{ github.run_number }}' path: build/artifacts/** - macos: + macos11: name: "macOS 11 (${{ matrix.build.name }} x86_64)" runs-on: macos-11 + strategy: fail-fast: false matrix: build: - name: Regular ODR + slug: -ODR type: Release + dev-build: off new-dynarec: off strip: --strip - name: Debug ODR - slug: -Debug + slug: -ODR-Debug type: Debug + dev-build: off + new-dynarec: off + - name: Dev ODR + slug: -ODR-Dev + type: Debug + dev-build: on new-dynarec: off - name: Regular NDR slug: -NDR type: Release strip: --strip + dev-build: off new-dynarec: on - name: Debug NDR slug: -NDR-Debug type: Debug + dev-build: off + new-dynarec: on + - name: Dev NDR + slug: -NDR-Dev + type: Debug + dev-build: on new-dynarec: on steps: diff --git a/CMakePresets.json b/CMakePresets.json index 2cfd8ea4a..8ff0e502c 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -34,6 +34,18 @@ "NEW_DYNAREC": "OFF" } }, + { + "name": "regularndr", + "inherits": [ + "flags-base" + ], + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "DEV_BRANCH": "OFF", + "NEW_DYNAREC": "ON" + } + }, { "name": "optimized", "inherits": [ @@ -46,6 +58,18 @@ "NEW_DYNAREC": "OFF" } }, + { + "name": "optimizedndr", + "inherits": [ + "flags-base" + ], + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Optimized", + "DEV_BRANCH": "OFF", + "NEW_DYNAREC": "ON" + } + }, { "name": "debug", "inherits": [ @@ -58,12 +82,36 @@ "NEW_DYNAREC": "OFF" } }, + { + "name": "debugndr", + "inherits": [ + "flags-base" + ], + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "DEV_BRANCH": "OFF", + "NEW_DYNAREC": "ON" + } + }, { "name": "experimental", "inherits": [ "flags-base" ], "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "DEV_BRANCH": "ON", + "NEW_DYNAREC": "OFF" + } + }, + { + "name": "experimentalndr", + "inherits": [ + "flags-base" + ], + "generator": "Ninja", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "DEV_BRANCH": "ON", diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index e21b96c4b..9583123b0 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -99,8 +99,12 @@ extern const device_t gus_device; extern const device_t pas16_device; #endif +/* IBM PS/1 Audio Card */ +extern const device_t ps1snd_device; + /* Tandy PSSJ */ extern const device_t pssj_device; +extern const device_t pssj_isa_device; /* Creative Labs Sound Blaster */ extern const device_t sb_1_device; diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 708879fdd..c8b1cca8c 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -15,6 +15,8 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ +#ifndef VIDEO_CGA_H +# define VIDEO_CGA_H typedef struct cga_t { @@ -65,3 +67,5 @@ void cga_poll(void *p); extern const device_config_t cga_config[]; extern const device_t cga_device; #endif + +#endif /*VIDEO_CGA_H*/ diff --git a/src/include/86box/vid_cga_comp.h b/src/include/86box/vid_cga_comp.h index 5ce52e61a..6b1dc4062 100644 --- a/src/include/86box/vid_cga_comp.h +++ b/src/include/86box/vid_cga_comp.h @@ -16,6 +16,8 @@ * Copyright 2015-2018 reenigne. * Copyright 2015-2018 Miran Grca. */ +#ifndef VIDEO_CGA_COMP_H +# define VIDEO_CGA_COMP_H #define Bit8u uint8_t #define Bit32u uint32_t @@ -25,3 +27,5 @@ void update_cga16_color(uint8_t cgamode); void cga_comp_init(int revision); Bit32u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit32u *TempLine); + +#endif /*VIDEO_CGA_COMP_H*/ diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h new file mode 100644 index 000000000..8d44fdfe1 --- /dev/null +++ b/src/include/86box/vid_hercules.h @@ -0,0 +1,61 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Hercules graphics cards. + * + * + * + * Author: Sarah Walker, + * Miran Grca, + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2021 Jasmine Iwanek. + */ +#ifndef VIDEO_HERCULES_H +# define VIDEO_HERCULES_H + +typedef struct { + mem_mapping_t mapping; + + uint8_t crtc[32], charbuffer[4096]; + int crtcreg; + + uint8_t ctrl, + ctrl2, + stat; + + uint64_t dispontime, + dispofftime; + pc_timer_t timer; + + int firstline, + lastline; + + int linepos, + displine; + int vc, + sc; + uint16_t ma, + maback; + int con, coff, + cursoron; + int dispon, + blink; + int vsynctime; + int vadj; + + int lp_ff; + + int cols[256][2][2]; + + uint8_t *vram; +} hercules_t; + +static void *hercules_init(const device_t *info); + +#endif /*VIDEO_HERCULES_H*/ diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 47bb84e0f..348677477 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -16,6 +16,8 @@ * Copyright 2008-2020 Sarah Walker. * Copyright 2016-2020 Miran Grca. */ +#ifndef VIDEO_SVGA_H +# define VIDEO_SVGA_H #define FLAG_EXTRA_BANKS 1 @@ -306,3 +308,5 @@ extern const device_t tseng_ics5301_ramdac_device; extern const device_t tseng_ics5341_ramdac_device; extern const device_t tvp3026_ramdac_device; #endif + +#endif /*VIDEO_SVGA_H*/ diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h new file mode 100644 index 000000000..c8a9b132e --- /dev/null +++ b/src/include/86box/vid_vga.h @@ -0,0 +1,34 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the IBM MDA + VGA graphics cards. + * + * + * + * Author: Sarah Walker, + * Miran Grca, + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2021 Jasmine Iwanek. + */ +#ifndef VIDEO_VGA_H +# define VIDEO_VGA_H + +typedef struct vga_t +{ + svga_t svga; + + rom_t bios_rom; +} vga_t; + +static video_timings_t timing_vga = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; + +void vga_out(uint16_t addr, uint8_t val, void *p); +uint8_t vga_in(uint16_t addr, void *p); + +#endif /*VIDEO_VGA_H*/ diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 4c5c26dbc..47b8121e0 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -60,26 +60,11 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/port_6x.h> -#include <86box/sound.h> -#include <86box/snd_sn76489.h> #include <86box/video.h> #include <86box/machine.h> +#include <86box/sound.h> -typedef struct { - sn76489_t sn76489; - uint8_t status, ctrl; - uint64_t timer_latch; - pc_timer_t timer_count; - int timer_enable; - uint8_t fifo[2048]; - int fifo_read_idx, fifo_write_idx; - int fifo_threshold; - uint8_t dac_val; - int16_t buffer[SOUNDBUFLEN]; - int pos; -} ps1snd_t; - typedef struct { int model; @@ -100,178 +85,6 @@ typedef struct { } ps1_t; -static void -update_irq_status(ps1snd_t *snd) -{ - if (((snd->status & snd->ctrl) & 0x12) && (snd->ctrl & 0x01)) - picint(1 << 7); - else - picintc(1 << 7); -} - - -static uint8_t -snd_read(uint16_t port, void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - uint8_t ret = 0xff; - - switch (port & 7) { - case 0: /* ADC data */ - snd->status &= ~0x10; - update_irq_status(snd); - ret = 0; - break; - - case 2: /* status */ - ret = snd->status; - ret |= (snd->ctrl & 0x01); - if ((snd->fifo_write_idx - snd->fifo_read_idx) >= 2048) - ret |= 0x08; /* FIFO full */ - if (snd->fifo_read_idx == snd->fifo_write_idx) - ret |= 0x04; /* FIFO empty */ - break; - - case 3: /* FIFO timer */ - /* - * The PS/1 Technical Reference says this should return - * thecurrent value, but the PS/1 BIOS and Stunt Island - * expect it not to change. - */ - ret = snd->timer_latch; - break; - - case 4: - case 5: - case 6: - case 7: - ret = 0; - } - - return(ret); -} - - -static void -snd_write(uint16_t port, uint8_t val, void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - - switch (port & 7) { - case 0: /* DAC output */ - if ((snd->fifo_write_idx - snd->fifo_read_idx) < 2048) { - snd->fifo[snd->fifo_write_idx & 2047] = val; - snd->fifo_write_idx++; - } - break; - - case 2: /* control */ - snd->ctrl = val; - if (! (val & 0x02)) - snd->status &= ~0x02; - update_irq_status(snd); - break; - - case 3: /* timer reload value */ - snd->timer_latch = val; - if (val) - timer_set_delay_u64(&snd->timer_count, ((0xff-val) * TIMER_USEC)); - else - timer_disable(&snd->timer_count); - break; - - case 4: /* almost empty */ - snd->fifo_threshold = val * 4; - break; - } -} - - -static void -snd_update(ps1snd_t *snd) -{ - for (; snd->pos < sound_pos_global; snd->pos++) - snd->buffer[snd->pos] = (int8_t)(snd->dac_val ^ 0x80) * 0x20; -} - - -static void -snd_callback(void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - - snd_update(snd); - - if (snd->fifo_read_idx != snd->fifo_write_idx) { - snd->dac_val = snd->fifo[snd->fifo_read_idx & 2047]; - snd->fifo_read_idx++; - } - - if ((snd->fifo_write_idx - snd->fifo_read_idx) == snd->fifo_threshold) - snd->status |= 0x02; /*FIFO almost empty*/ - - snd->status |= 0x10; /*ADC data ready*/ - update_irq_status(snd); - - timer_advance_u64(&snd->timer_count, snd->timer_latch * TIMER_USEC); -} - - -static void -snd_get_buffer(int32_t *buffer, int len, void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - int c; - - snd_update(snd); - - for (c = 0; c < len * 2; c++) - buffer[c] += snd->buffer[c >> 1]; - - snd->pos = 0; -} - - -static void * -snd_init(const device_t *info) -{ - ps1snd_t *snd; - - snd = malloc(sizeof(ps1snd_t)); - memset(snd, 0x00, sizeof(ps1snd_t)); - - sn76489_init(&snd->sn76489, 0x0205, 0x0001, SN76496, 4000000); - - io_sethandler(0x0200, 1, snd_read,NULL,NULL, snd_write,NULL,NULL, snd); - io_sethandler(0x0202, 6, snd_read,NULL,NULL, snd_write,NULL,NULL, snd); - - timer_add(&snd->timer_count, snd_callback, snd, 0); - - sound_add_handler(snd_get_buffer, snd); - - return(snd); -} - - -static void -snd_close(void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - - free(snd); -} - - -static const device_t snd_device = { - "PS/1 Audio Card", - 0, 0, - snd_init, snd_close, NULL, - { NULL }, - NULL, - NULL -}; - - static void recalc_memory(ps1_t *ps) { @@ -470,7 +283,7 @@ ps1_setup(int model) lpt2_remove(); - device_add(&snd_device); + device_add(&ps1snd_device); device_add(&fdc_at_ps1_device); @@ -499,7 +312,7 @@ ps1_setup(int model) device_add(&ide_isa_device); - device_add(&snd_device); + device_add(&ps1snd_device); } } diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index d7da82713..464e5c45a 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -15,7 +15,7 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_resid.cc midi.c midi_rtmidi.cpp snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c - snd_lpt_dss.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c + snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c snd_azt2316a.c snd_cms.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c) diff --git a/src/sound/snd_ps1.c b/src/sound/snd_ps1.c new file mode 100644 index 000000000..e9455a327 --- /dev/null +++ b/src/sound/snd_ps1.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/sound.h> +#include <86box/snd_sn76489.h> + + +typedef struct { + sn76489_t sn76489; + uint8_t status, ctrl; + uint64_t timer_latch; + pc_timer_t timer_count; + int timer_enable; + uint8_t fifo[2048]; + int fifo_read_idx, fifo_write_idx; + int fifo_threshold; + uint8_t dac_val; + int16_t buffer[SOUNDBUFLEN]; + int pos; +} ps1snd_t; + + +static void +ps1snd_update_irq_status(ps1snd_t *snd) +{ + if (((snd->status & snd->ctrl) & 0x12) && (snd->ctrl & 0x01)) + picint(1 << 7); + else + picintc(1 << 7); +} + + +static uint8_t +ps1snd_read(uint16_t port, void *priv) +{ + ps1snd_t *ps1snd = (ps1snd_t *)priv; + uint8_t ret = 0xff; + + switch (port & 7) { + case 0: /* ADC data */ + ps1snd->status &= ~0x10; + ps1snd_update_irq_status(ps1snd); + ret = 0; + break; + + case 2: /* status */ + ret = ps1snd->status; + ret |= (ps1snd->ctrl & 0x01); + if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) >= 2048) + ret |= 0x08; /* FIFO full */ + if (ps1snd->fifo_read_idx == ps1snd->fifo_write_idx) + ret |= 0x04; /* FIFO empty */ + break; + + case 3: /* FIFO timer */ + /* + * The PS/1 Technical Reference says this should return + * thecurrent value, but the PS/1 BIOS and Stunt Island + * expect it not to change. + */ + ret = ps1snd->timer_latch; + break; + + case 4: + case 5: + case 6: + case 7: + ret = 0; + } + + return(ret); +} + + +static void +ps1snd_write(uint16_t port, uint8_t val, void *priv) +{ + ps1snd_t *ps1snd = (ps1snd_t *)priv; + + switch (port & 7) { + case 0: /* DAC output */ + if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) < 2048) { + ps1snd->fifo[ps1snd->fifo_write_idx & 2047] = val; + ps1snd->fifo_write_idx++; + } + break; + + case 2: /* control */ + ps1snd->ctrl = val; + if (! (val & 0x02)) + ps1snd->status &= ~0x02; + ps1snd_update_irq_status(ps1snd); + break; + + case 3: /* timer reload value */ + ps1snd->timer_latch = val; + if (val) + timer_set_delay_u64(&ps1snd->timer_count, ((0xff-val) * TIMER_USEC)); + else + timer_disable(&ps1snd->timer_count); + break; + + case 4: /* almost empty */ + ps1snd->fifo_threshold = val * 4; + break; + } +} + + +static void +ps1snd_update(ps1snd_t *ps1snd) +{ + for (; ps1snd->pos < sound_pos_global; ps1snd->pos++) + ps1snd->buffer[ps1snd->pos] = (int8_t)(ps1snd->dac_val ^ 0x80) * 0x20; +} + + +static void +ps1snd_callback(void *priv) +{ + ps1snd_t *ps1snd = (ps1snd_t *)priv; + + ps1snd_update(ps1snd); + + if (ps1snd->fifo_read_idx != ps1snd->fifo_write_idx) { + ps1snd->dac_val = ps1snd->fifo[ps1snd->fifo_read_idx & 2047]; + ps1snd->fifo_read_idx++; + } + + if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) == ps1snd->fifo_threshold) + ps1snd->status |= 0x02; /*FIFO almost empty*/ + + ps1snd->status |= 0x10; /*ADC data ready*/ + ps1snd_update_irq_status(ps1snd); + + timer_advance_u64(&ps1snd->timer_count, ps1snd->timer_latch * TIMER_USEC); +} + + +static void +ps1snd_get_buffer(int32_t *buffer, int len, void *priv) +{ + ps1snd_t *ps1snd = (ps1snd_t *)priv; + int c; + + ps1snd_update(ps1snd); + + for (c = 0; c < len * 2; c++) + buffer[c] += ps1snd->buffer[c >> 1]; + + ps1snd->pos = 0; +} + + +static void * +ps1snd_init(const device_t *info) +{ + ps1snd_t *ps1snd = malloc(sizeof(ps1snd_t)); + memset(ps1snd, 0x00, sizeof(ps1snd_t)); + + sn76489_init(&ps1snd->sn76489, 0x0205, 0x0001, SN76496, 4000000); + + io_sethandler(0x0200, 1, ps1snd_read,NULL,NULL, ps1snd_write,NULL,NULL, ps1snd); + io_sethandler(0x0202, 6, ps1snd_read,NULL,NULL, ps1snd_write,NULL,NULL, ps1snd); + + timer_add(&ps1snd->timer_count, ps1snd_callback, ps1snd, 0); + + sound_add_handler(ps1snd_get_buffer, ps1snd); + + return(ps1snd); +} + + +static void +ps1snd_close(void *priv) +{ + ps1snd_t *ps1snd = (ps1snd_t *)priv; + + free(ps1snd); +} + + +const device_t ps1snd_device = { + "IBM PS/1 Audio Card", + 0, 0, + ps1snd_init, ps1snd_close, + NULL, + { NULL }, + NULL, + NULL, + NULL +}; diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index 4eab5c856..6ef24c679 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -15,233 +15,289 @@ typedef struct pssj_t { - sn76489_t sn76489; - - uint8_t ctrl; - uint8_t wave; - uint8_t dac_val; - uint16_t freq; - int amplitude; - - int irq; - pc_timer_t timer_count; - int enable; - - int wave_pos; - int pulse_width; + sn76489_t sn76489; - int16_t buffer[SOUNDBUFLEN]; - int pos; + uint8_t ctrl; + uint8_t wave; + uint8_t dac_val; + uint16_t freq; + int amplitude; + + int irq; + pc_timer_t timer_count; + int enable; + + int wave_pos; + int pulse_width; + + int16_t buffer[SOUNDBUFLEN]; + int pos; } pssj_t; static void pssj_update_irq(pssj_t *pssj) { - if (pssj->irq && (pssj->ctrl & 0x10) && (pssj->ctrl & 0x08)) - picint(1 << 7); + if (pssj->irq && (pssj->ctrl & 0x10) && (pssj->ctrl & 0x08)) + picint(1 << 7); } static void pssj_write(uint16_t port, uint8_t val, void *p) { - pssj_t *pssj = (pssj_t *)p; + pssj_t *pssj = (pssj_t *)p; - switch (port & 3) - { - case 0: - pssj->ctrl = val; - if (!pssj->enable && ((val & 4) && (pssj->ctrl & 3))) - timer_set_delay_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); - pssj->enable = (val & 4) && (pssj->ctrl & 3); - if (!pssj->enable) - timer_disable(&pssj->timer_count); - sn74689_set_extra_divide(&pssj->sn76489, val & 0x40); - if (!(val & 8)) - pssj->irq = 0; - pssj_update_irq(pssj); - break; - case 1: - switch (pssj->ctrl & 3) - { - case 1: /*Sound channel*/ - pssj->wave = val; - pssj->pulse_width = val & 7; - break; - case 3: /*Direct DAC*/ - pssj->dac_val = val; - break; - } - break; - case 2: - pssj->freq = (pssj->freq & 0xf00) | val; - break; - case 3: - pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8); - pssj->amplitude = val >> 4; - break; - } + switch (port & 3) + { + case 0: + pssj->ctrl = val; + if (!pssj->enable && ((val & 4) && (pssj->ctrl & 3))) + timer_set_delay_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); + pssj->enable = (val & 4) && (pssj->ctrl & 3); + if (!pssj->enable) + timer_disable(&pssj->timer_count); + sn74689_set_extra_divide(&pssj->sn76489, val & 0x40); + if (!(val & 8)) + pssj->irq = 0; + pssj_update_irq(pssj); + break; + case 1: + switch (pssj->ctrl & 3) + { + case 1: /*Sound channel*/ + pssj->wave = val; + pssj->pulse_width = val & 7; + break; + case 3: /*Direct DAC*/ + pssj->dac_val = val; + break; + } + break; + case 2: + pssj->freq = (pssj->freq & 0xf00) | val; + break; + case 3: + pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8); + pssj->amplitude = val >> 4; + break; + } } static uint8_t pssj_read(uint16_t port, void *p) { - pssj_t *pssj = (pssj_t *)p; - - switch (port & 3) - { - case 0: - return (pssj->ctrl & ~0x88) | (pssj->irq ? 8 : 0); - case 1: - switch (pssj->ctrl & 3) - { - case 0: /*Joystick*/ - return 0; - case 1: /*Sound channel*/ - return pssj->wave; - case 2: /*Successive approximation*/ - return 0x80; - case 3: /*Direct DAC*/ - return pssj->dac_val; - } - break; - case 2: - return pssj->freq & 0xff; - case 3: - return (pssj->freq >> 8) | (pssj->amplitude << 4); - default: - return 0xff; - } + pssj_t *pssj = (pssj_t *)p; - return 0xff; + switch (port & 3) + { + case 0: + return (pssj->ctrl & ~0x88) | (pssj->irq ? 8 : 0); + case 1: + switch (pssj->ctrl & 3) + { + case 0: /*Joystick*/ + return 0; + case 1: /*Sound channel*/ + return pssj->wave; + case 2: /*Successive approximation*/ + return 0x80; + case 3: /*Direct DAC*/ + return pssj->dac_val; + } + break; + case 2: + return pssj->freq & 0xff; + case 3: + return (pssj->freq >> 8) | (pssj->amplitude << 4); + default: + return 0xff; + } + + return 0xff; } static void pssj_update(pssj_t *pssj) { - for (; pssj->pos < sound_pos_global; pssj->pos++) - pssj->buffer[pssj->pos] = (((int8_t)(pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15; + for (; pssj->pos < sound_pos_global; pssj->pos++) + pssj->buffer[pssj->pos] = (((int8_t)(pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15; } static void pssj_callback(void *p) { - pssj_t *pssj = (pssj_t *)p; - int data; + pssj_t *pssj = (pssj_t *)p; + int data; - pssj_update(pssj); - if (pssj->ctrl & 2) + pssj_update(pssj); + if (pssj->ctrl & 2) + { + if ((pssj->ctrl & 3) == 3) { - if ((pssj->ctrl & 3) == 3) - { - data = dma_channel_read(1); + data = dma_channel_read(1); - if (data != DMA_NODATA) - { - pssj->dac_val = data & 0xff; - } - } - else - { - data = dma_channel_write(1, 0x80); - } - - if ((data & DMA_OVER) && data != DMA_NODATA) - { - if (pssj->ctrl & 0x08) - { - pssj->irq = 1; - pssj_update_irq(pssj); - } - } + if (data != DMA_NODATA) + { + pssj->dac_val = data & 0xff; + } } else { - switch (pssj->wave & 0xc0) - { - case 0x00: /*Pulse*/ - pssj->dac_val = (pssj->wave_pos > (pssj->pulse_width << 1)) ? 0xff : 0; - break; - case 0x40: /*Ramp*/ - pssj->dac_val = pssj->wave_pos << 3; - break; - case 0x80: /*Triangle*/ - if (pssj->wave_pos & 16) - pssj->dac_val = (pssj->wave_pos ^ 31) << 4; - else - pssj->dac_val = pssj->wave_pos << 4; - break; - case 0xc0: - pssj->dac_val = 0x80; - break; - } - pssj->wave_pos = (pssj->wave_pos + 1) & 31; + data = dma_channel_write(1, 0x80); } - timer_advance_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); + if ((data & DMA_OVER) && data != DMA_NODATA) + { + if (pssj->ctrl & 0x08) + { + pssj->irq = 1; + pssj_update_irq(pssj); + } + } + } + else + { + switch (pssj->wave & 0xc0) + { + case 0x00: /*Pulse*/ + pssj->dac_val = (pssj->wave_pos > (pssj->pulse_width << 1)) ? 0xff : 0; + break; + case 0x40: /*Ramp*/ + pssj->dac_val = pssj->wave_pos << 3; + break; + case 0x80: /*Triangle*/ + if (pssj->wave_pos & 16) + pssj->dac_val = (pssj->wave_pos ^ 31) << 4; + else + pssj->dac_val = pssj->wave_pos << 4; + break; + case 0xc0: + pssj->dac_val = 0x80; + break; + } + pssj->wave_pos = (pssj->wave_pos + 1) & 31; + } + + timer_advance_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); } static void pssj_get_buffer(int32_t *buffer, int len, void *p) { - pssj_t *pssj = (pssj_t *)p; - int c; - - pssj_update(pssj); - - for (c = 0; c < len * 2; c++) - buffer[c] += pssj->buffer[c >> 1]; + pssj_t *pssj = (pssj_t *)p; + int c; - pssj->pos = 0; + pssj_update(pssj); + + for (c = 0; c < len * 2; c++) + buffer[c] += pssj->buffer[c >> 1]; + + pssj->pos = 0; } void *pssj_init(const device_t *info) { - pssj_t *pssj = malloc(sizeof(pssj_t)); - memset(pssj, 0, sizeof(pssj_t)); + pssj_t *pssj = malloc(sizeof(pssj_t)); + memset(pssj, 0, sizeof(pssj_t)); - sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); + sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); - io_sethandler(0x00C4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); - timer_add(&pssj->timer_count, pssj_callback, pssj, pssj->enable); - sound_add_handler(pssj_get_buffer, pssj); - - return pssj; + io_sethandler(0x00C4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); + timer_add(&pssj->timer_count, pssj_callback, pssj, pssj->enable); + sound_add_handler(pssj_get_buffer, pssj); + + return pssj; } void *pssj_1e0_init(const device_t *info) { - pssj_t *pssj = malloc(sizeof(pssj_t)); - memset(pssj, 0, sizeof(pssj_t)); + pssj_t *pssj = malloc(sizeof(pssj_t)); + memset(pssj, 0, sizeof(pssj_t)); - sn76489_init(&pssj->sn76489, 0x01e0, 0x0004, PSSJ, 3579545); + sn76489_init(&pssj->sn76489, 0x01e0, 0x0004, PSSJ, 3579545); - io_sethandler(0x01E4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); - timer_add(&pssj->timer_count, pssj_callback, pssj, pssj->enable); - sound_add_handler(pssj_get_buffer, pssj); - - return pssj; + io_sethandler(0x01E4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); + timer_add(&pssj->timer_count, pssj_callback, pssj, pssj->enable); + sound_add_handler(pssj_get_buffer, pssj); + + return pssj; +} + +void *pssj_isa_init(const device_t *info) +{ + pssj_t *pssj = malloc(sizeof(pssj_t)); + memset(pssj, 0, sizeof(pssj_t)); + + sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); + + uint16_t addr = device_get_config_hex16("base"); + + io_sethandler(addr, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); + timer_add(&pssj->timer_count, pssj_callback, pssj, pssj->enable); + sound_add_handler(pssj_get_buffer, pssj); + + return pssj; } void pssj_close(void *p) { - pssj_t *pssj = (pssj_t *)p; + pssj_t *pssj = (pssj_t *)p; - free(pssj); + free(pssj); } +static const device_config_t pssj_isa_config[] = +{ + { + "base", "Address", CONFIG_HEX16, "", 0xC0, "", { 0 }, + { + { + "0xC0", 0xC0 + }, + { + "0x1E0", 0x1E0 + }, + { + "0x2C0", 0x2C0 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + const device_t pssj_device = { - "Tandy PSSJ", - 0, 0, - pssj_init, - pssj_close, - NULL, - { NULL }, - NULL, - NULL + "Tandy PSSJ", + 0, + 0, + pssj_init, + pssj_close, + NULL, + { NULL }, + NULL, + NULL }; const device_t pssj_1e0_device = { - "Tandy PSSJ (port 1e0h)", - 0, 0, - pssj_1e0_init, - pssj_close, - NULL, - { NULL }, - NULL, - NULL + "Tandy PSSJ (port 1e0h)", + 0, + 0, + pssj_1e0_init, + pssj_close, + NULL, + { NULL }, + NULL, + NULL +}; + +const device_t pssj_isa_device = +{ + "Tandy PSSJ (ISA Clone)", + DEVICE_ISA, + 0, + pssj_isa_init, + pssj_close, + NULL, + { NULL }, + NULL, + NULL, + pssj_isa_config }; diff --git a/src/sound/sound.c b/src/sound/sound.c index af9a91460..892f6a689 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -85,6 +85,7 @@ static const SOUND_CARD sound_cards[] = { { "none", NULL }, { "internal", NULL }, + { "pssj_isa", &pssj_isa_device }, { "adlib", &adlib_device }, { "adlibgold", &adgold_device }, { "azt2316a", &azt2316a_device }, diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 6c9660bb8..1dd60a3e4 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -31,45 +31,9 @@ #include <86box/pit.h> #include <86box/device.h> #include <86box/video.h> +#include <86box/vid_hercules.h> -typedef struct { - mem_mapping_t mapping; - - uint8_t crtc[32], charbuffer[4096]; - int crtcreg; - - uint8_t ctrl, - ctrl2, - stat; - - uint64_t dispontime, - dispofftime; - pc_timer_t timer; - - int firstline, - lastline; - - int linepos, - displine; - int vc, - sc; - uint16_t ma, - maback; - int con, coff, - cursoron; - int dispon, - blink; - int vsynctime; - int vadj; - - int lp_ff; - - int cols[256][2][2]; - - uint8_t *vram; -} hercules_t; - static video_timings_t timing_hercules = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 4c081e1a7..bd05fea46 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -1249,7 +1249,8 @@ enum TGUI_BITBLT = 1, TGUI_SCANLINE = 3, TGUI_BRESENHAMLINE = 4, - TGUI_SHORTVECTOR = 5 + TGUI_SHORTVECTOR = 5, + TGUI_FASTLINE = 6 }; enum @@ -1480,7 +1481,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) tgui->accel.right >>= 2; } } - + switch (tgui->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP)) { case TGUI_SRCCPU: @@ -1572,31 +1573,36 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } while (count--) { - src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col); - if (tgui->accel.bpp == 0) - src_dat &= 0xff; - else if (tgui->accel.bpp == 1) - src_dat &= 0xffff; + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && + tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom)) { + src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col); + if (tgui->accel.bpp == 0) + src_dat &= 0xff; + else if (tgui->accel.bpp == 1) + src_dat &= 0xffff; - READ(tgui->accel.dst, dst_dat); + READ(tgui->accel.dst, dst_dat); - pat_dat = pattern_data[((tgui->accel.pat_y & 7)*8) + (tgui->accel.pat_x & 7)]; + pat_dat = pattern_data[((tgui->accel.pat_y & 7)*8) + (tgui->accel.pat_x & 7)]; - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; - if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { - MIX(); + if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { + MIX(); - WRITE(tgui->accel.dst, out); + WRITE(tgui->accel.dst, out); + } } cpu_dat <<= 1; tgui->accel.src += xdir; tgui->accel.dst += xdir; tgui->accel.pat_x += xdir; + if (tgui->type >= TGUI_9660) + tgui->accel.dx += xdir; tgui->accel.x++; if (tgui->accel.x > tgui->accel.size_x) { @@ -1605,6 +1611,11 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) tgui->accel.pat_x = tgui->accel.dst_x; tgui->accel.pat_y += ydir; + if (tgui->type >= TGUI_9660) { + tgui->accel.dx = tgui->accel.dst_x & 0xfff; + tgui->accel.dy += ydir; + } + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); @@ -1891,6 +1902,88 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } } break; + + case TGUI_FASTLINE: + { + if (tgui->type < TGUI_9660) + break; + + int16_t dx, dy; + + dx = tgui->accel.dst_x & 0xfff; + dy = tgui->accel.dst_y & 0xfff; + + tgui->accel.left = tgui->accel.src_x_clip & 0xfff; + tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; + tgui->accel.top = tgui->accel.src_y_clip & 0xfff; + tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; + + if (tgui->accel.bpp == 1) { + tgui->accel.left >>= 1; + tgui->accel.right >>= 1; + } else if (tgui->accel.bpp == 3) { + tgui->accel.left >>= 2; + tgui->accel.right >>= 2; + } + + while (count--) { + READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); + + /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right && + dy >= tgui->accel.top && dy <= tgui->accel.bottom)) { + READ(dx + (dy * tgui->accel.pitch), dst_dat); + + pat_dat = tgui->accel.fg_col; + + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; + + MIX(); + + WRITE(dx + (dy * tgui->accel.pitch), out); + } + + if (tgui->accel.y == (tgui->accel.size_y & 0xfff)) + break; + + switch ((tgui->accel.size_y >> 8) & 0xe0) { + case 0x00: + dx++; + break; + case 0x20: + dx++; + dy--; + break; + case 0x40: + dy--; + break; + case 0x60: + dx--; + dy--; + break; + case 0x80: + dx--; + break; + case 0xa0: + dx--; + dy++; + break; + case 0xc0: + dy++; + break; + case 0xe0: + dx++; + dy++; + break; + } + + tgui->accel.y++; + } + } + break; } } diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 3c872705b..b9f18348b 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -29,16 +29,9 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/vid_vga.h> -typedef struct vga_t -{ - svga_t svga; - - rom_t bios_rom; -} vga_t; - -static video_timings_t timing_vga = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; static video_timings_t timing_ps1_svga_isa = {VIDEO_ISA, 6, 8, 16, 6, 8, 16}; static video_timings_t timing_ps1_svga_mca = {VIDEO_MCA, 6, 8, 16, 6, 8, 16}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index cae57102b..cfcef28ab 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -650,6 +650,7 @@ SNDOBJ := sound.o \ midi.o midi_rtmidi.o \ snd_speaker.o \ snd_pssj.o \ + snd_ps1.o \ snd_lpt_dac.o snd_lpt_dss.o \ snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \ snd_ac97_codec.o snd_ac97_via.o \