diff --git a/CMakeLists.txt b/CMakeLists.txt index caa4aaa90..d3f74da8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 3.8 + VERSION 3.11 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) diff --git a/debian/changelog b/debian/changelog index 8ccc46aab..0ec15e546 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -86box (3.7.1-1) UNRELEASED; urgency=medium +86box (3.11.0-1) UNRELEASED; urgency=medium * Initial release. - -- Mariusz Kurek Wed, 19 Oct 2022 21:06:00 +0200 + -- Jasmine Iwanek Sun, 18 Nov 2022 23:27:00 -0500 diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index c1237e97e..dcbfde9ed 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -411,7 +411,7 @@ kbd_poll(void *priv) kbd->blocked = 1; picint(2); #ifdef ENABLE_KEYBOARD_XT_LOG - kbd_log("kbd_poll(): keyboard_xt : take IRQ\n"); + kbd_log("XTkbd: kbd_poll(): keyboard_xt : take IRQ\n"); #endif } @@ -517,6 +517,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) xtkbd_t *kbd = (xtkbd_t *) priv; uint8_t bit, set, new_clock; + switch (port) { case 0x61: /* Keyboard Control Register (aka Port B) */ if (!(val & 0x80)) { @@ -556,18 +557,18 @@ kbd_write(uint16_t port, uint8_t val, void *priv) #ifdef ENABLE_KEYBOARD_XT_LOG if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) - kbd_log("Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); + kbd_log("XTkbd: Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); #endif break; #ifdef ENABLE_KEYBOARD_XT_LOG case 0x62: /* Switch Register (aka Port C) */ if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) - kbd_log("Cassette IN is %i\n", !!(val & 0x10)); + kbd_log("XTkbd: Cassette IN is %i\n", !!(val & 0x10)); break; #endif case 0xc0 ... 0xcf: /* Pravetz Flags */ - kbd_log("Port %02X out: %02X\n", port, val); + kbd_log("XTkbd: Port %02X out: %02X\n", port, val); if (kbd->type == KBD_TYPE_PRAVETZ) { bit = (port >> 1) & 0x07; set = (port & 0x01) << bit; @@ -680,7 +681,7 @@ kbd_read(uint16_t port, void *priv) case 0xc0: /* Pravetz Flags */ if (kbd->type == KBD_TYPE_PRAVETZ) ret = kbd->pravetz_flags; - kbd_log("Port %02X in : %02X\n", port, ret); + kbd_log("XTkbd: Port %02X in : %02X\n", port, ret); break; } diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index dca0b22c5..89a921c5a 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -292,10 +292,29 @@ typedef struct { } hd_type_t; hd_type_t hd_types[4] = { - {306, 4, MFM_SECTORS}, /* type 0 */ - { 612, 4, MFM_SECTORS}, /* type 16 */ - { 615, 4, MFM_SECTORS}, /* type 2 */ - { 306, 8, MFM_SECTORS} /* type 13 */ + { 306, 4, MFM_SECTORS}, /* type 0 */ + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 615, 4, MFM_SECTORS}, /* type 2 */ + { 306, 8, MFM_SECTORS} /* type 13 */ +}; + +hd_type_t hd_types_olivetti[16] = { + { 697, 5, MFM_SECTORS}, + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 306, 4, MFM_SECTORS}, /* type 0 */ + { 612, 8, MFM_SECTORS}, + { 820, 6, MFM_SECTORS}, + { 820, 6, MFM_SECTORS}, + { 823, 10, MFM_SECTORS}, + { 981, 5, MFM_SECTORS}, + { 981, 5, MFM_SECTORS}, + {1024, 8, MFM_SECTORS}, + {1024, 9, MFM_SECTORS}, + { 872, 5, MFM_SECTORS}, + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 306, 4, MFM_SECTORS} /* "not present" with the second hard disk */ }; #ifdef ENABLE_ST506_XT_LOG @@ -1430,29 +1449,40 @@ loadhd(hdc_t *dev, int c, int d, const char *fn) /* Set the "drive type" switches for the IBM Xebec controller. */ static void -set_switches(hdc_t *dev) +set_switches(hdc_t *dev, hd_type_t *hdt, int num) { drive_t *drive; int c, d; + int e; dev->switches = 0x00; for (d = 0; d < MFM_NUM; d++) { drive = &dev->drives[d]; - if (!drive->present) + if (!drive->present) { + if (dev->type == ST506_XT_TYPE_WD1002A_WX1_NOBIOS) + dev->switches |= (0x33 << (d ? 0 : 2)); continue; + } - for (c = 0; c < 4; c++) { - if ((drive->spt == hd_types[c].spt) && (drive->hpc == hd_types[c].hpc) && (drive->tracks == hd_types[c].tracks)) { - dev->switches |= (c << (d ? 0 : 2)); + for (c = 0; c < num; c++) { + /* Does the Xebec also support more than 4 types? */ + if ((drive->spt == hdt[c].spt) && (drive->hpc == hdt[c].hpc) && (drive->tracks == hdt[c].tracks)) { + /* Olivetti M24/M240: Move the upper 2 bites up by 2 bits, as the + layout is as follows: D0_3 D0_2 D1_3 D1_2 D0_1 D0_0 D1_1 D1_0. */ + if (dev->type == ST506_XT_TYPE_WD1002A_WX1_NOBIOS) + e = (c & 0x03) | ((c >> 2) << 4); + else + e = c; + dev->switches |= (e << (d ? 0 : 2)); break; } } #ifdef ENABLE_ST506_XT_LOG st506_xt_log("ST506: "); - if (c == 4) + if (c == num) st506_xt_log("*WARNING* drive%i unsupported", d); else st506_xt_log("drive%i is type %i", d, c); @@ -1538,16 +1568,9 @@ st506_init(const device_t *info) break; case ST506_XT_TYPE_WD1002A_WX1_NOBIOS: /* Western Digital WD1002A-WX1 (MFM, No BIOS) */ + /* Supported base addresses: 320h, 324h, 328h, 32Ch. */ dev->nr_err = ERR_NOT_AVAILABLE; fn = NULL; - /* The switches are read in reverse: 0 = closed, 1 = open. - Both open means MFM, 17 sectors per track. */ - dev->switches = 0x30; /* autobios */ - dev->base = device_get_config_hex16("base"); - dev->irq = device_get_config_int("irq"); - if (dev->irq == 2) - dev->switches |= 0x40; - dev->bios_addr = device_get_config_hex20("bios_addr"); break; case ST506_XT_TYPE_WD1004A_WX1: /* Western Digital WD1004A-WX1 (MFM) */ @@ -1650,7 +1673,9 @@ st506_init(const device_t *info) /* For the Xebec, set the switches now. */ if (dev->type == ST506_XT_TYPE_XEBEC) - set_switches(dev); + set_switches(dev, (hd_type_t *) hd_types, 4); + else if (dev->type == ST506_XT_TYPE_WD1002A_WX1_NOBIOS) + set_switches(dev, (hd_type_t *) hd_types_olivetti, 16); /* Initial "active" drive parameters. */ for (c = 0; c < MFM_NUM; c++) { diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index ed9011608..93e96d5eb 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -383,13 +383,11 @@ fdd_is_dd(int drive) return (drive_types[fdd[drive].type].flags & 0x70) == 0x10; } -#if 0 int fdd_is_hd(int drive) { return drive_types[fdd[drive].type].flags & FLAG_HOLE1; } -#endif int fdd_is_ed(int drive) diff --git a/src/include/86box/fdd.h b/src/include/86box/fdd.h index a580a824a..412843eb0 100644 --- a/src/include/86box/fdd.h +++ b/src/include/86box/fdd.h @@ -42,9 +42,7 @@ extern int fdd_can_read_medium(int drive); extern int fdd_doublestep_40(int drive); extern int fdd_is_525(int drive); extern int fdd_is_dd(int drive); -#if 0 extern int fdd_is_hd(int drive); -#endif extern int fdd_is_ed(int drive); extern int fdd_is_double_sided(int drive); extern void fdd_set_head(int drive, int head); diff --git a/src/include/86box/rom.h b/src/include/86box/rom.h index 8cc85934d..82a1aef5f 100644 --- a/src/include/86box/rom.h +++ b/src/include/86box/rom.h @@ -51,38 +51,38 @@ extern uint8_t rom_read(uint32_t addr, void *p); extern uint16_t rom_readw(uint32_t addr, void *p); extern uint32_t rom_readl(uint32_t addr, void *p); -extern FILE *rom_fopen(char *fn, char *mode); +extern FILE *rom_fopen(const char *fn, char *mode); extern int rom_getfile(char *fn, char *s, int size); extern int rom_present(char *fn); -extern int rom_load_linear_oddeven(char *fn, uint32_t addr, int sz, +extern int rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr); -extern int rom_load_linear(char *fn, uint32_t addr, int sz, +extern int rom_load_linear(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr); -extern int rom_load_interleaved(char *fnl, char *fnh, uint32_t addr, +extern int rom_load_interleaved(const char *fnl, const char *fnh, uint32_t addr, int sz, int off, uint8_t *ptr); extern uint8_t bios_read(uint32_t addr, void *priv); extern uint16_t bios_readw(uint32_t addr, void *priv); extern uint32_t bios_readl(uint32_t addr, void *priv); -extern int bios_load(char *fn1, char *fn2, uint32_t addr, int sz, +extern int bios_load(const char *fn1, const char *fn2, uint32_t addr, int sz, int off, int flags); -extern int bios_load_linear_combined(char *fn1, char *fn2, +extern int bios_load_linear_combined(const char *fn1, const char *fn2, int sz, int off); -extern int bios_load_linear_combined2(char *fn1, char *fn2, - char *fn3, char *fn4, char *fn5, +extern int bios_load_linear_combined2(const char *fn1, const char *fn2, + const char *fn3, const char *fn4, const char *fn5, int sz, int off); -extern int bios_load_linear_combined2_ex(char *fn1, char *fn2, - char *fn3, char *fn4, char *fn5, +extern int bios_load_linear_combined2_ex(const char *fn1, const char *fn2, + const char *fn3, const char *fn4, const char *fn5, int sz, int off); -extern int rom_init(rom_t *rom, char *fn, uint32_t address, int size, +extern int rom_init(rom_t *rom, const char *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags); -extern int rom_init_oddeven(rom_t *rom, char *fn, uint32_t address, int size, +extern int rom_init_oddeven(rom_t *rom, const char *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags); -extern int rom_init_interleaved(rom_t *rom, char *fn_low, - char *fn_high, uint32_t address, +extern int rom_init_interleaved(rom_t *rom, const char *fn_low, + const char *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags); diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index 38a411ada..5caccf8fc 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -21,6 +21,7 @@ enum fm_type { FM_YM3812 = 0, FM_YMF262, FM_YMF289B, + FM_YMF278B, FM_MAX }; @@ -51,6 +52,7 @@ extern const device_t ymf262_nuked_device; extern const device_t ym3812_ymfm_device; extern const device_t ymf262_ymfm_device; extern const device_t ymf289b_ymfm_device; +extern const device_t ymf278b_ymfm_device; #endif #endif /*SOUND_OPL_H*/ diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 22606b481..10303c3ca 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -81,6 +81,7 @@ extern const device_t adgold_device; /* Aztech Sound Galaxy 16 */ extern const device_t azt2316a_device; extern const device_t acermagic_s20_device; +extern const device_t mirosound_pcm10_device; extern const device_t azt1605_device; /* Ensoniq AudioPCI */ diff --git a/src/include_make/86box/version.h b/src/include_make/86box/version.h index 78a6dc2f1..e4792969c 100644 --- a/src/include_make/86box/version.h +++ b/src/include_make/86box/version.h @@ -22,11 +22,11 @@ #define EMU_NAME "86Box" #define EMU_NAME_W LSTR(EMU_NAME) -#define EMU_VERSION "3.8" +#define EMU_VERSION "3.11" #define EMU_VERSION_W LSTR(EMU_VERSION) #define EMU_VERSION_EX "3.50" /* frozen due to IDE re-detection behavior on Windows */ #define EMU_VERSION_MAJ 3 -#define EMU_VERSION_MIN 8 +#define EMU_VERSION_MIN 11 #define EMU_VERSION_PATCH 0 #define EMU_BUILD_NUM 0 @@ -42,7 +42,7 @@ #define EMU_ROMS_URL "https://github.com/86Box/roms/releases/latest" #define EMU_ROMS_URL_W LSTR(EMU_ROMS_URL) #ifdef RELEASE_BUILD -# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v3.8/" +# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v3.11/" #else # define EMU_DOCS_URL "https://86box.readthedocs.io" #endif diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 9ad782a14..193015186 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -28,6 +28,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> #include <86box/io.h> @@ -47,6 +48,7 @@ #include <86box/gameport.h> #include <86box/hdc.h> #include <86box/port_6x.h> +#include <86box/serial.h> #include <86box/sound.h> #include <86box/snd_speaker.h> #include <86box/video.h> @@ -120,8 +122,9 @@ typedef struct { uint8_t status; uint8_t out; uint8_t output_port; + uint8_t id; int param, - param_total; + param_total; uint8_t params[16]; uint8_t scan[7]; @@ -145,23 +148,22 @@ video_timings_t timing_m19_vid = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; const device_t m19_vid_device; -#ifdef ENABLE_M24VID_LOG -int m24vid_do_log = ENABLE_M24VID_LOG; +#ifdef ENABLE_XT_OLIVETTI_LOG +int xt_olivetti_do_log = ENABLE_XT_OLIVETTI_LOG; static void -m24_log(const char *fmt, ...) +xt_olivetti_log(const char *fmt, ...) { va_list ap; - if (m24vid_do_log) { + if (xt_olivetti_do_log) { va_start(ap, fmt); - vfprintf(stdlog, fmt, ap); + pclog_ex(fmt, ap); va_end(ap); - fflush(stdlog); } } #else -# define m24_log(fmt, ...) +# define xt_olivetti_log(fmt, ...) #endif /* Set the chip time. */ @@ -488,16 +490,12 @@ m24_kbd_poll(void *priv) if (m24_kbd->wantirq) { m24_kbd->wantirq = 0; picint(2); -#if ENABLE_KEYBOARD_LOG - m24_log("M24: take IRQ\n"); -#endif + xt_olivetti_log("M24: take IRQ\n"); } if (!(m24_kbd->status & STAT_OFULL) && key_queue_start != key_queue_end) { -#if ENABLE_KEYBOARD_LOG - m24_log("Reading %02X from the key queue at %i\n", - m24_kbd->out, key_queue_start); -#endif + xt_olivetti_log("Reading %02X from the key queue at %i\n", + m24_kbd->out, key_queue_start); m24_kbd->out = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; m24_kbd->status |= STAT_OFULL; @@ -519,21 +517,32 @@ m24_kbd_adddata_ex(uint16_t val) kbd_adddata_process(val, m24_kbd_adddata); } +/* + From the Olivetti M21/M24 Theory of Operation: + + Port Function + ---- -------- + 60h Keyboard 8041 Data Transfer Read/Write + 61h Control Port A Read/Write + 62h Control Port B Read + 63h Not Used + 64h Keyboard 8041 Command/Status + 65h Communications Port Read + 66h System Configuration Read + 67h System Configuration Read + */ static void m24_kbd_write(uint16_t port, uint8_t val, void *priv) { m24_kbd_t *m24_kbd = (m24_kbd_t *) priv; + uint8_t ret; -#if ENABLE_KEYBOARD_LOG - m24_log("M24: write %04X %02X\n", port, val); -#endif + xt_olivetti_log("M24: write %04X %02X\n", port, val); -#if 0 - if (ram[8] == 0xc3) - output = 3; -#endif switch (port) { case 0x60: + m24_kbd->status &= ~STAT_CD; + if (m24_kbd->param != m24_kbd->param_total) { m24_kbd->params[m24_kbd->param++] = val; if (m24_kbd->param == m24_kbd->param_total) { @@ -557,17 +566,38 @@ m24_kbd_write(uint16_t port, uint8_t val, void *priv) break; default: - m24_log("M24: bad keyboard command complete %02X\n", m24_kbd->command); + xt_olivetti_log("M24: bad keyboard command complete %02X\n", m24_kbd->command); } } } else { m24_kbd->command = val; switch (val) { + /* 01: FD, 05: ANY ---> Customer test reports no keyboard. + 01: AA, 05: 01 ---> Customer test reports 102 Deluxe keyboard. + 01: AA, 05: 02 ---> Customer test reports 83-key keyboard. + 01: AA, 05: 10 ---> Customer test reports M240 keyboard. + 01: AA, 05: 20 ---> Customer test reports 101/102/key keyboard. + 01: AA, 05: 40 or anything else ---> Customer test reports 101/102/key keyboard. + + AA is the correct return for command 01, as confirmed by the M24 Customer Test. */ case 0x01: /*Self-test*/ + m24_kbd_adddata(0xaa); + break; + + case 0x02: /*Olivetti M240: Read SWB*/ + /* SWB on mainboard (off=1) + * bit 7 - use BIOS HD on mainboard (on) / on controller (off) + * bit 6 - use OCG/CGA display adapter (on) / other display adapter (off) + */ + ret = (hdc_current == HDC_INTERNAL) ? 0x00 : 0x80; + ret |= video_is_cga() ? 0x40 : 0x00; + + m24_kbd_adddata(ret); break; case 0x05: /*Read ID*/ - m24_kbd_adddata(0x00); + ret = m24_kbd->id; + m24_kbd_adddata(ret); break; case 0x11: @@ -580,8 +610,11 @@ m24_kbd_write(uint16_t port, uint8_t val, void *priv) m24_kbd->param_total = 4; break; + case 0x13: /*Sent by Olivetti M240 Customer Diagnostics*/ + break; + default: - m24_log("M24: bad keyboard command %02X\n", val); + xt_olivetti_log("M24: bad keyboard command %02X\n", val); } } break; @@ -596,9 +629,17 @@ m24_kbd_write(uint16_t port, uint8_t val, void *priv) was_speaker_enable = 1; pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); break; + + case 0x64: + m24_kbd->status |= STAT_CD; + + if (val == 0x02) + m24_kbd_adddata(0x00); } } +extern uint8_t random_generate(void); + static uint8_t m24_kbd_read(uint16_t port, void *priv) { @@ -621,16 +662,22 @@ m24_kbd_read(uint16_t port, void *priv) break; case 0x61: + /* MS-DOS 5.00 and higher's KEYB.COM freezes due to port 61h not having the + AT refresh toggle, because for some reson it thinks the M24 is an AT. + + A German-language site confirms this also happens on real hardware. + + The M240 is not affected. */ ret = ppi.pb; break; case 0x64: - ret = m24_kbd->status; + ret = m24_kbd->status & 0x0f; m24_kbd->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); break; default: - m24_log("\nBad M24 keyboard read %04X\n", port); + xt_olivetti_log("\nBad M24 keyboard read %04X\n", port); } return (ret); @@ -770,6 +817,561 @@ ms_poll(int x, int y, int z, int b, void *priv) return (0); } +/* Remapping as follows: + + - Left Windows (E0 5B) -> NUMPAD 00 (54); + - Print Screen (E0 37) -> SCR PRT (55); + - Menu (E0 5D) -> HELP (56); + - NumPad Enter (E0 1C) -> NUMPAD ENTER (57). + - Left (E0 4B) -> LEFT (58); + - Down (E0 50) -> DOWN (59); + - Right (E0 4D) -> RIGHT (5A); + - Up (E0 48) -> UP (5B); + - Page Up (E0 49) -> CLEAR (5C); + - Page Down (E0 51) -> BREAK (5D); + - CE Key (56) -> CE KEY (5E); + WARNING: The Olivetti CE Key is undocumented, but can be inferred from the fact + its position is missing in the shown layout, it being used by the Italian + keyboard layout, the keyboard is called 103-key, but only 102 keys are + shown. + - NumPad / (E0 35) -> NUMPAD / (5F); + - F11 (57) -> F11 (60); + - F12 (58) -> F12 (61); + - Insert (E0 52) -> F13 (62); + - Home (E0 47) -> F14 (63); + - Delete (E0 53) -> F15 (64); + - End (E0 4F) -> F16 (65); + - Right Alt (Gr)(E0 38) -> F16 (66); + - Right Windows (E0 5C) -> F18 (67). + */ +const scancode scancode_olivetti_m24_deluxe[512] = { + // clang-format off + { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, + { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, + { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, + { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, + { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, + { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, + { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, + { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, + { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, + { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, + { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, + { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, + { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, + { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, + { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, + { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, + { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, + { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, + { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, + { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, + { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, + { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, + { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, + { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, + { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, + { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, + { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, + { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, + { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, + { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, + { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, + { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, + { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, + { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, + { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, + { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, + { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, + { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, + { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, + { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, + { {0}, {0} }, { {0}, {0} }, + { {0x5e, 0}, {0xde, 0} }, { {0x60, 0}, {0xe0, 0} }, /*054*/ + { {0x61, 0}, {0xe1, 0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*058*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*05c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*060*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*064*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*068*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*06c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*070*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*074*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*078*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*07c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*080*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*084*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*088*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*08c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*090*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*094*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*098*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*09c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0fc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*100*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*104*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*108*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*10c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*110*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*114*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*118*/ + { {0x57, 0}, {0xd7, 0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*11c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*120*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*124*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*128*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*12c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*130*/ + { {0}, {0} }, { {0x5f, 0}, {0xdf, 0} }, + { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ + { {0x66, 0}, {0xe6, 0} }, { {0x55, 0}, {0xd5, 0} }, + { {0}, {0} }, { {0}, {0} }, /*138*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*13c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*140*/ + { {0}, {0} }, { {0}, {0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x63, 0}, {0xe3, 0} }, /*144*/ + { {0x5b, 0}, {0xdb, 0} }, { {0x5c, 0}, {0xdc, 0} }, + { {0}, {0} }, { {0x58, 0}, {0xd8, 0} }, /*148*/ + { {0}, {0} }, { {0x5a, 0}, {0xda, 0} }, + { {0}, {0} }, { {0x65, 0}, {0xe5, 0} }, /*14c*/ + { {0x59, 0}, {0xd9, 0} }, { {0x5d, 0}, {0xdd, 0} }, + { {0x62, 0}, {0xe2, 0} }, { {0x64, 0}, {0xe4, 0} }, /*150*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*154*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0x54, 0}, {0xd4, 0} }, /*158*/ + { {0x67, 0}, {0xe7, 0} }, { {0x56, 0}, {0xd6, 0} }, + { {0}, {0} }, { {0}, {0} }, /*15c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*160*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*164*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*168*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*16c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*170*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*174*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*148*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*17c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*180*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*184*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*88*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*18c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*190*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*194*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*198*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*19c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} } /*1fc*/ + // clang-format on +}; + +/* Remapping as follows: + + - Left Windows (E0 5B) -> 54; + - Right Windows (E0 5C) -> 56; + - Menu (E0 5D) -> 5C. + */ +const scancode scancode_olivetti_m240[512] = { + // clang-format off + { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, + { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, + { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, + { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, + { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, + { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, + { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, + { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, + { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, + { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, + { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, + { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, + { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, + { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, + { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, + { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, + { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, + { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, + { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, + { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, + { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, + { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, + { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, + { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, + { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, + { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, + { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, + { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, + { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, + { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, + { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, + { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, + { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, + { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, + { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, + { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, + { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, + { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, + { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, + { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*054*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*058*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*05c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*060*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*064*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*068*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*06c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*070*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*074*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*078*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*07c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*080*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*084*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*088*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*08c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*090*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*094*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*098*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*09c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0fc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*100*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*104*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*108*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*10c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*110*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*114*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*118*/ + { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, + { {0}, {0} }, { {0}, {0} }, /*11c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*120*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*124*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*128*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*12c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*130*/ + { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, + { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ + { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*138*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*13c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*140*/ + { {0}, {0} }, { {0}, {0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ + { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, + { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*148*/ + { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, + { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ + { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*154*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*158*/ + { {0}, {0} }, { {0x54, 0}, {0xd4, 0} }, + { {0x56, 0}, {0xd6, 0} }, { {0x5c, 0}, {0xdc, 0} }, /*15c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*160*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*164*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*168*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*16c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*170*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*174*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*148*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*17c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*180*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*184*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*88*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*18c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*190*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*194*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*198*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*19c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} } /*1fc*/ + // clang-format on +}; + static void m24_kbd_init(m24_kbd_t *kbd) { @@ -788,7 +1390,7 @@ m24_kbd_init(m24_kbd_t *kbd) mouse_set_buttons(2); mouse_set_poll(ms_poll, kbd); - keyboard_set_table(scancode_xt); + keyboard_set_table((kbd->id == 0x01) ? scancode_olivetti_m24_deluxe : scancode_olivetti_m240); keyboard_set_is_amstrad(0); } @@ -1004,6 +1606,16 @@ m24_read(uint16_t port, void *priv) int i, fdd_count = 0; switch (port) { + case 0x62: + /* Control Port B Read */ + ret = 0xff; + break; + + case 0x65: + /* Communications Port Read */ + ret = 0xff; + break; + /* * port 66: * DIPSW-0 on mainboard (off=present=1) @@ -1042,6 +1654,7 @@ m24_read(uint16_t port, void *priv) break; } break; + /* * port 67: * DIPSW-1 on mainboard (off=present=1) @@ -1078,18 +1691,82 @@ m24_read(uint16_t port, void *priv) else ret |= 0x0; + /* Switch 4 - The M21/M24 Theory of Operation says + "Reserved for HDU", same as for Switch 3 */ + /* Switch 3 - Disable internal BIOS HD */ - ret |= 0x4; + if (hdc_current != HDC_INTERNAL) + ret |= 0x4; /* Switch 2 - Set fast startup */ ret |= 0x2; - + + /* 1 = 720 kB (3.5"), 0 = 360 kB (5.25") */ + ret |= (fdd_doublestep_40(0) || fdd_doublestep_40(1)) ? 0x1 : 0x0; break; } return (ret); } +static uint8_t +m240_read(uint16_t port, void *priv) +{ + uint8_t ret = 0x00; + int i, fdd_count = 0; + + switch (port) { + case 0x62: + /* SWA on Olivetti M240 mainboard (off=1) */ + ret = 0x00; + if (ppi.pb & 0x8) { + /* Switches 4, 5 - floppy drives (number) */ + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 2); + /* Switches 6, 7 - monitor type */ + if (video_is_mda()) + ret |= 0x3; + else if (video_is_cga()) + ret |= 0x2; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + } else { + /* bit 2 always on */ + ret |= 0x4; + /* Switch 8 - 8087 FPU. */ + if (hasfpu) + ret |= 0x02; + } + break; + + case 0x63: + /* Olivetti M240 SWB: + - Bit 7: 1 = MFDD (= high-density) unit present (Customer Test will then always think Drive 2 is absent), + 0 = MFD unit absent; + - Bit 6: 1 = Second drive is 3.5" (for low density drive, this means 80-track), + 0 = Second drive is 5.25" (for low density drive, this means 40-track). + - Bit 5: 1 = First drive is 3.5" (for low density drive, this means 80-track), + 0 = First drive is 5.25" (for low density drive, this means 40-track). + */ + + ret = (fdd_is_hd(0) || fdd_is_hd(1)) ? 0x80 : 0x00; + ret |= fdd_doublestep_40(1) ? 0x40 : 0x00; + ret |= fdd_doublestep_40(0) ? 0x20 : 0x00; + break; + } + + return (ret); +} + +/* + * Uses M21/M24/M240 keyboard controller and M24 102/103-key Deluxe keyboard. + */ int machine_xt_m24_init(const machine_t *model) { @@ -1114,7 +1791,7 @@ machine_xt_m24_init(const machine_t *model) device_add(&fdc_xt_device); /* Address 66-67 = mainboard dip-switch settings */ - io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0x0065, 3, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); standalone_gameport_type = &gameport_device; @@ -1133,20 +1810,29 @@ machine_xt_m24_init(const machine_t *model) if (gfxcard == VID_INTERNAL) device_add(&ogc_m24_device); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + io_sethandler(0x0062, 1, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); + + m24_kbd->id = 0x01; + m24_kbd_init(m24_kbd); device_add_ex(&m24_kbd_device, m24_kbd); + if (hdc_current == HDC_INTERNAL) + device_add(&st506_xt_wd1002a_wx1_nobios_device); + return ret; } /* - * Current bugs: - * - handles only 360kb floppy drives (drive type and capacity selectable with jumpers mapped to unknown memory locations) + * Uses M21/M24/M240 keyboard controller and M240 keyboard. */ int machine_xt_m240_init(const machine_t *model) { int ret; + m24_kbd_t *m24_kbd; nvr_t *nvr; ret = bios_load_interleaved("roms/machines/m240/olivetti_m240_pch6_2.04_low.bin", @@ -1156,12 +1842,15 @@ machine_xt_m240_init(const machine_t *model) if (bios_only || !ret) return ret; + m24_kbd = (m24_kbd_t *) malloc(sizeof(m24_kbd_t)); + memset(m24_kbd, 0x00, sizeof(m24_kbd_t)); + machine_common_init(model); pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); /* Address 66-67 = mainboard dip-switch settings */ - io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0x0062, 2, m240_read, NULL, NULL, NULL, NULL, NULL, NULL); /* * port 60: should return jumper settings only under unknown conditions @@ -1169,11 +1858,13 @@ machine_xt_m240_init(const machine_t *model) * bit 7 - use BIOS HD on mainboard (on) / on controller (off) * bit 6 - use OCG/CGA display adapter (on) / other display adapter (off) */ - device_add(&keyboard_at_olivetti_device); - device_add(&port_6x_olivetti_device); + m24_kbd->id = 0x10; + + m24_kbd_init(m24_kbd); + device_add_ex(&m24_kbd_device, m24_kbd); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + device_add(&fdc_at_device); /* io.c logs clearly show it using port 3F7 */ if (joystick_type) device_add(&gameport_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 9938c6664..9259e1a8d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2065,7 +2065,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PC, - .flags = MACHINE_VIDEO | MACHINE_MOUSE, + .flags = MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_MFM, .ram = { .min = 128, .max = 640, diff --git a/src/mem/rom.c b/src/mem/rom.c index 40457298d..6c964f2c3 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -87,7 +87,7 @@ rom_add_path(const char *path) } FILE * -rom_fopen(char *fn, char *mode) +rom_fopen(const char *fn, char *mode) { char temp[1024]; rom_path_t *rom_path; @@ -205,7 +205,7 @@ rom_readl(uint32_t addr, void *priv) } int -rom_load_linear_oddeven(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { FILE *f = rom_fopen(fn, "rb"); int i; @@ -241,7 +241,7 @@ rom_load_linear_oddeven(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) /* Load a ROM BIOS from its chips, interleaved mode. */ int -rom_load_linear(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_linear(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { FILE *f = rom_fopen(fn, "rb"); @@ -270,7 +270,7 @@ rom_load_linear(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) /* Load a ROM BIOS from its chips, linear mode with high bit flipped. */ int -rom_load_linear_inverted(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_linear_inverted(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { FILE *f = rom_fopen(fn, "rb"); @@ -308,7 +308,7 @@ rom_load_linear_inverted(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) /* Load a ROM BIOS from its chips, interleaved mode. */ int -rom_load_interleaved(char *fnl, char *fnh, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_interleaved(const char *fnl, const char *fnh, uint32_t addr, int sz, int off, uint8_t *ptr) { FILE *fl = rom_fopen(fnl, "rb"); FILE *fh = rom_fopen(fnh, "rb"); @@ -478,7 +478,7 @@ bios_add(void) /* These four are for loading the BIOS. */ int -bios_load(char *fn1, char *fn2, uint32_t addr, int sz, int off, int flags) +bios_load(const char *fn1, const char *fn2, uint32_t addr, int sz, int off, int flags) { uint8_t ret = 0; uint8_t *ptr = NULL; @@ -525,7 +525,7 @@ bios_load(char *fn1, char *fn2, uint32_t addr, int sz, int off, int flags) } int -bios_load_linear_combined(char *fn1, char *fn2, int sz, int off) +bios_load_linear_combined(const char *fn1, const char *fn2, int sz, int off) { uint8_t ret = 0; @@ -536,7 +536,7 @@ bios_load_linear_combined(char *fn1, char *fn2, int sz, int off) } int -bios_load_linear_combined2(char *fn1, char *fn2, char *fn3, char *fn4, char *fn5, int sz, int off) +bios_load_linear_combined2(const char *fn1, const char *fn2, const char *fn3, const char *fn4, const char *fn5, int sz, int off) { uint8_t ret = 0; @@ -551,7 +551,7 @@ bios_load_linear_combined2(char *fn1, char *fn2, char *fn3, char *fn4, char *fn5 } int -bios_load_linear_combined2_ex(char *fn1, char *fn2, char *fn3, char *fn4, char *fn5, int sz, int off) +bios_load_linear_combined2_ex(const char *fn1, const char *fn2, const char *fn3, const char *fn4, const char *fn5, int sz, int off) { uint8_t ret = 0; @@ -566,7 +566,7 @@ bios_load_linear_combined2_ex(char *fn1, char *fn2, char *fn3, char *fn4, char * } int -rom_init(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) +rom_init(rom_t *rom, const char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) { rom_log("rom_init(%08X, %s, %08X, %08X, %08X, %08X, %08X)\n", rom, fn, addr, sz, mask, off, flags); @@ -595,7 +595,7 @@ rom_init(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, uint32_ } int -rom_init_oddeven(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) +rom_init_oddeven(rom_t *rom, const char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) { rom_log("rom_init(%08X, %08X, %08X, %08X, %08X, %08X, %08X)\n", rom, fn, addr, sz, mask, off, flags); @@ -624,7 +624,7 @@ rom_init_oddeven(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, } int -rom_init_interleaved(rom_t *rom, char *fnl, char *fnh, uint32_t addr, int sz, int mask, int off, uint32_t flags) +rom_init_interleaved(rom_t *rom, const char *fnl, const char *fnh, uint32_t addr, int sz, int mask, int off, uint32_t flags) { /* Allocate a buffer for the image. */ rom->rom = malloc(sz); diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index f58f815e1..d9ddcec83 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -410,10 +410,10 @@ msgid "Sound card:" msgstr "Placa de som:" msgid "MIDI Out Device:" -msgstr "Disp. saída MIDI:" +msgstr "Disp. de saída MIDI:" msgid "MIDI In Device:" -msgstr "Disp. entrada MIDI:" +msgstr "Disp. de entrada MIDI:" msgid "Standalone MPU-401" msgstr "MPU-401 autônomo" @@ -539,7 +539,7 @@ msgid "&Remove" msgstr "&Remover" msgid "Bus:" -msgstr "Bar.:" +msgstr "Barramento:" msgid "Channel:" msgstr "Canal:" diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 409467725..21cc66f04 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -64,6 +64,11 @@ fm_driver_get(int chip_id, fm_drv_t *drv) drv->priv = device_add_inst(&ymf289b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); break; + case FM_YMF278B: + *drv = ymfm_drv; + drv->priv = device_add_inst(&ymf278b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); + break; + default: return 0; } diff --git a/src/sound/snd_opl_ymfm.cpp b/src/sound/snd_opl_ymfm.cpp index 1e9f5f9b5..d1f0ed4c4 100644 --- a/src/sound/snd_opl_ymfm.cpp +++ b/src/sound/snd_opl_ymfm.cpp @@ -27,6 +27,8 @@ extern "C" { #include <86box/device.h> #include <86box/sound.h> #include <86box/snd_opl.h> +#include <86box/mem.h> +#include <86box/rom.h> } #define RSM_FRAC 10 @@ -62,6 +64,7 @@ public: virtual void generate_resampled(int32_t *data, uint32_t num_samples) = 0; virtual int32_t *update() = 0; virtual uint8_t read(uint16_t addr) = 0; + virtual void set_clock(uint32_t clock) = 0; protected: int32_t m_buffer[SOUNDBUFLEN * 2]; @@ -78,6 +81,7 @@ public: , m_chip(*this) , m_clock(clock) , m_samplecnt(0) + , m_samplerate(samplerate) { memset(m_samples, 0, sizeof(m_samples)); memset(m_oldsamples, 0, sizeof(m_oldsamples)); @@ -87,6 +91,12 @@ public: m_subtract[1] = 320.0; m_type = type; + if (m_type == FM_YMF278B) { + if (rom_load_linear("roms/sound/yamaha/yrw801.rom", 0, 0x200000, 0, m_yrw801) == 0) { + fatal("YRW801 ROM image \"roms/sound/yamaha/yrw801.rom\" not found\n"); + } + } + timer_add(&m_timers[0], YMFMChip::timer1, this, 0); timer_add(&m_timers[1], YMFMChip::timer2, this, 0); } @@ -101,7 +111,8 @@ public: if (tnum > 1) return; - pc_timer_t *timer = &m_timers[tnum]; + m_duration_in_clocks[tnum] = duration_in_clocks; + pc_timer_t *timer = &m_timers[tnum]; if (duration_in_clocks < 0) timer_stop(timer); else { @@ -113,16 +124,26 @@ public: } } + virtual void set_clock(uint32_t clock) override + { + m_clock = clock; + m_clock_us = 1000000 / (double) m_clock; + m_rateratio = (m_samplerate << RSM_FRAC) / m_chip.sample_rate(m_clock); + + ymfm_set_timer(0, m_duration_in_clocks[0]); + ymfm_set_timer(1, m_duration_in_clocks[1]); + } + virtual void generate(int32_t *data, uint32_t num_samples) override { for (uint32_t i = 0; i < num_samples; i++) { m_chip.generate(&m_output); if (ChipType::OUTPUTS == 1) { - *data++ = m_output.data[0]; - *data++ = m_output.data[0]; + *data++ = m_output.data[(m_type == FM_YMF278B) ? 4 : 0]; + *data++ = m_output.data[(m_type == FM_YMF278B) ? 4 : 0]; } else { - *data++ = m_output.data[0]; - *data++ = m_output.data[1 % ChipType::OUTPUTS]; + *data++ = m_output.data[(m_type == FM_YMF278B) ? 4 : 0]; + *data++ = m_output.data[(m_type == FM_YMF278B) ? 5 : (1 % ChipType::OUTPUTS)]; } } } @@ -135,11 +156,11 @@ public: m_oldsamples[1] = m_samples[1]; m_chip.generate(&m_output); if (ChipType::OUTPUTS == 1) { - m_samples[0] = m_output.data[0]; - m_samples[1] = m_output.data[0]; + m_samples[0] = m_output.data[(m_type == FM_YMF278B) ? 4 : 0]; + m_samples[1] = m_output.data[(m_type == FM_YMF278B) ? 4 : 0]; } else { - m_samples[0] = m_output.data[0]; - m_samples[1] = m_output.data[1 % ChipType::OUTPUTS]; + m_samples[0] = m_output.data[(m_type == FM_YMF278B) ? 4 : 0]; + m_samples[1] = m_output.data[(m_type == FM_YMF278B) ? 5 : (1 % ChipType::OUTPUTS)]; } m_samplecnt -= m_rateratio; } @@ -182,7 +203,7 @@ public: virtual uint32_t get_special_flags(void) override { - return ((m_type == FM_YMF262) || (m_type == FM_YMF289B)) ? 0x8000 : 0x0000; + return ((m_type == FM_YMF262) || (m_type == FM_YMF289B) || (m_type == FM_YMF278B)) ? 0x8000 : 0x0000; } static void timer1(void *priv) @@ -197,12 +218,25 @@ public: drv->m_engine->engine_timer_expired(1); } + virtual uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address) override + { + if (type == ymfm::access_class::ACCESS_PCM && address < 0x200000) { + return m_yrw801[address]; + } + return 0xFF; + } + private: ChipType m_chip; uint32_t m_clock; double m_clock_us, m_subtract[2]; typename ChipType::output_data m_output; pc_timer_t m_timers[2]; + int32_t m_duration_in_clocks[2]; // Needed for clock switches. + uint32_t m_samplerate; + + // YRW801-M wavetable ROM. + uint8_t m_yrw801[0x200000]; // Resampling int32_t m_rateratio; @@ -237,7 +271,7 @@ ymfm_log(const char *fmt, ...) va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); - } + } } #else # define ymfm_log(fmt, ...) @@ -261,6 +295,10 @@ ymfm_drv_init(const device_t *info) case FM_YMF289B: fm = (YMFMChipBase *) new YMFMChip(33868800, FM_YMF289B, 48000); break; + + case FM_YMF278B: + fm = (YMFMChipBase *) new YMFMChip(33868800, FM_YMF278B, 48000); + break; } fm->set_do_cycles(1); @@ -282,6 +320,7 @@ ymfm_drv_read(uint16_t port, void *priv) { YMFMChipBase *drv = (YMFMChipBase *) priv; + if (port == 0x381) { port += 4; } /* Point to register read port. */ if (drv->flags() & FLAG_CYCLES) { cycles -= ((int) (isa_timing * 8)); } @@ -298,6 +337,7 @@ ymfm_drv_write(uint16_t port, uint8_t val, void *priv) { YMFMChipBase *drv = (YMFMChipBase *) priv; ymfm_log("YMFM write port %04x value = %02x\n", port, val); + if (port == 0x380 || port == 0x381) { port += 4; } drv->write(port, val); drv->update(); } @@ -367,6 +407,20 @@ const device_t ymf289b_ymfm_device = { .config = NULL }; +const device_t ymf278b_ymfm_device = { + .name = "Yamaha YMF278B OPL4 (YMFM)", + .internal_name = "ymf289b_ymfm", + .flags = 0, + .local = FM_YMF278B, + .init = ymfm_drv_init, + .close = ymfm_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const fm_drv_t ymfm_drv { &ymfm_drv_read, &ymfm_drv_write, diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index d2aca8345..3280a47ef 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * OPTi MediaCHIPS 82C929 audio controller emulation. + * OPTi MediaCHIPS 82C929 (also known as OPTi MAD16 Pro) audio controller emulation. * * * @@ -37,13 +37,15 @@ #include <86box/gameport.h> #include <86box/snd_ad1848.h> #include <86box/snd_sb.h> +#include <86box/mem.h> +#include <86box/rom.h> static int optimc_wss_dma[4] = { 0, 0, 1, 3 }; static int optimc_wss_irq[8] = { 5, 7, 9, 10, 11, 12, 14, 15 }; /* W95 only uses 7-10, others may be wrong */ enum optimc_local_flags { OPTIMC_CS4231 = 0x100, - OPTIMC_OPL4 = 0x200, /* Unused */ + OPTIMC_OPL4 = 0x200, }; typedef struct optimc_t { @@ -84,7 +86,8 @@ optimc_wss_write(uint16_t addr, uint8_t val, void *priv) { optimc_t *optimc = (optimc_t *) priv; - if (!(optimc->regs[4] & 0x10) && optimc->cur_mode == 0) return; + if (!(optimc->regs[4] & 0x10) && optimc->cur_mode == 0) + return; optimc->wss_config = val; ad1848_setdma(&optimc->ad1848, optimc_wss_dma[val & 3]); ad1848_setirq(&optimc->ad1848, optimc_wss_irq[(val >> 3) & 7]); @@ -121,8 +124,6 @@ optimc_remove_opl(optimc_t *optimc) static void optimc_add_opl(optimc_t *optimc) { - fm_driver_get(FM_YMF262, &optimc->sb->opl); - /* DSP I/O handler is activated in sb_dsp_setaddr */ io_sethandler(optimc->cur_addr + 0, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); io_sethandler(optimc->cur_addr + 8, 0x0002, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); @@ -184,8 +185,6 @@ optimc_reg_write(uint16_t addr, uint8_t val, void *p) } case 1: /* MC2 */ optimc->regs[1] = val; - if (old != val) - optimc_reload_opl(optimc); break; case 2: /* MC3 */ if (val == optimc->type) @@ -228,8 +227,6 @@ optimc_reg_write(uint16_t addr, uint8_t val, void *p) break; case 3: /* MC4 */ optimc->regs[3] = val; - if ((old & 0x8) != (val & 0x8)) - optimc_reload_opl(optimc); break; case 4: /* MC5 */ optimc->regs[4] = val; @@ -347,7 +344,7 @@ optimc_init(const device_t *info) optimc->regs[1] = 0x03; optimc->regs[2] = 0x00; optimc->regs[3] = 0x00; - optimc->regs[4] = 0x2F; + optimc->regs[4] = 0x3F; optimc->regs[5] = 0x83; optimc->gameport = gameport_add(&gameport_device); @@ -375,11 +372,14 @@ optimc_init(const device_t *info) sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma); sb_ct1345_mixer_reset(optimc->sb); - optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF289B : FM_YMF262; + optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262; fm_driver_get(optimc->fm_type, &optimc->sb->opl); io_sethandler(optimc->cur_addr + 0, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); io_sethandler(optimc->cur_addr + 8, 0x0002, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); io_sethandler(0x0388, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + if (optimc->fm_type == FM_YMF278B) { + io_sethandler(0x380, 2, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + } io_sethandler(optimc->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, optimc->sb); @@ -399,7 +399,7 @@ optimc_init(const device_t *info) static void optimc_close(void *p) { - optimc_t* optimc = (optimc_t*)p; + optimc_t *optimc = (optimc_t *) p; sb_close(optimc->sb); free(optimc->mpu); @@ -415,6 +415,12 @@ optimc_speed_changed(void *p) sb_speed_changed(optimc->sb); } +static int +mirosound_pcm10_available(void) +{ + return rom_present("roms/sound/yamaha/yrw801.rom"); +} + static const device_config_t acermagic_s20_config[] = { // clang-format off { @@ -441,12 +447,11 @@ static const device_config_t acermagic_s20_config[] = { // clang-format on }; - const device_t acermagic_s20_device = { .name = "AcerMagic S20", .internal_name = "acermagic_s20", .flags = DEVICE_ISA | DEVICE_AT, - .local = 0xE3 | 0x100, + .local = 0xE3 | OPTIMC_CS4231, .init = optimc_init, .close = optimc_close, .reset = NULL, @@ -454,4 +459,18 @@ const device_t acermagic_s20_device = { .speed_changed = optimc_speed_changed, .force_redraw = NULL, .config = acermagic_s20_config +}; + +const device_t mirosound_pcm10_device = { + .name = "miroSOUND PCM10", + .internal_name = "mirosound_pcm10", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0xE3 | OPTIMC_OPL4, + .init = optimc_init, + .close = optimc_close, + .reset = NULL, + { .available = mirosound_pcm10_available }, + .speed_changed = optimc_speed_changed, + .force_redraw = NULL, + .config = acermagic_s20_config }; \ No newline at end of file diff --git a/src/sound/sound.c b/src/sound/sound.c index 1efdef79b..cda851137 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -110,6 +110,7 @@ static const SOUND_CARD sound_cards[] = { { &sound_none_device }, { &sound_internal_device }, { &acermagic_s20_device }, + { &mirosound_pcm10_device }, { &adlib_device }, { &adgold_device }, { &azt2316a_device }, diff --git a/src/sound/ymfm/ymfm_pcm.h b/src/sound/ymfm/ymfm_pcm.h index 2022a69b9..b471fa611 100644 --- a/src/sound/ymfm/ymfm_pcm.h +++ b/src/sound/ymfm/ymfm_pcm.h @@ -212,8 +212,8 @@ public: uint32_t result = memory_address(); uint32_t newval = result + 1; m_regdata[0x05] = newval >> 0; - m_regdata[0x06] = newval >> 8; - m_regdata[0x07] = (newval >> 16) & 0x3f; + m_regdata[0x04] = newval >> 8; + m_regdata[0x03] = (newval >> 16) & 0x3f; return result; } diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index c6378dddf..414a38a96 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -15,7 +15,7 @@ %global romver v3.7 Name: 86Box -Version: 3.8 +Version: 3.11 Release: 1%{?dist} Summary: Classic PC emulator License: GPLv2+ @@ -117,5 +117,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Tue Aug 30 2022 Robert de Rooy 3.8-1 +* Fri Nov 18 2022 Robert de Rooy 3.11-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index 21e84b16a..3cd4b9ba2 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -10,7 +10,7 @@ net.86box.86Box.desktop - + diff --git a/src/win/languages/pt-BR.rc b/src/win/languages/pt-BR.rc index 541bd2ca1..8d16a2a48 100644 --- a/src/win/languages/pt-BR.rc +++ b/src/win/languages/pt-BR.rc @@ -37,7 +37,7 @@ BEGIN MENUITEM "&Ocultar barra de status", IDM_VID_HIDE_STATUS_BAR MENUITEM "Ocultar &barra de ferramenta", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Mostrar monitores não-primários", IDM_VID_MONITORS MENUITEM "&Janela redimensionável", IDM_VID_RESIZE MENUITEM "&Lembrar tamanho e posição", IDM_VID_REMEMBER MENUITEM SEPARATOR @@ -338,7 +338,7 @@ END #define STR_BUS "Bar.:" #define STR_CHANNEL "Canal:" #define STR_ID "ID:" -#define STR_SPEED "Speed:" +#define STR_SPEED "Velocidade:" #define STR_SPECIFY "&Especificar..." #define STR_SECTORS "Setores:" @@ -428,7 +428,7 @@ BEGIN IDS_2084 "CA" IDS_2085 "SE" IDS_2086 "MB" - IDS_2087 "Speed" + IDS_2087 "Velocidade" IDS_2088 "Verificar BPB" IDS_2089 "KB" IDS_2090 "Não foi possível inicializar o renderizador de vídeo." diff --git a/vcpkg.json b/vcpkg.json index 0bf171db8..f3f420b33 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "86box", - "version-string": "3.8", + "version-string": "3.11", "homepage": "https://86box.net/", "documentation": "http://86box.readthedocs.io/", "license": "GPL-2.0-or-later",